Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ variables:
resources:
pipelines:
- pipeline: CoOrdinatedBuildPipeline
source: 'PowerShell-Coordinated_Packages-NonOfficial'
source: 'PowerShell-Coordinated Binaries-NonOfficial'
trigger:
branches:
include:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ resources:

pipelines:
- pipeline: CoOrdinatedBuildPipeline
source: 'PowerShell-Coordinated_Packages-NonOfficial'
source: 'PowerShell-Coordinated Binaries-NonOfficial'

- pipeline: PSPackagesOfficial
source: 'PowerShell-Packages-NonOfficial'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ resources:

pipelines:
- pipeline: CoOrdinatedBuildPipeline
source: 'PowerShell-Coordinated_Packages-NonOfficial'
source: 'PowerShell-Coordinated Binaries-NonOfficial'

# NOTE: The alias name "PSPackagesOfficial" is intentionally reused here even
# for the NonOfficial pipeline source. Downstream shared templates (for example,
Expand Down
128 changes: 128 additions & 0 deletions .pipelines/templates/job/globaltool-pointer-job.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Collects the RID-specific 'PowerShell' global tool nupkgs built in parallel (as matrix legs
# of ONE job, see job/globaltool-rid-job.yml), assembles the RID-agnostic pointer package (see
# New-GlobalToolPointerNupkgSource in tools/packaging/packaging.psm1), signs everything
# together, and publishes the full set as this job's own output.
#
# ob_artifactBaseName is set explicitly (rather than relying on OneBranch's auto-derived
# drop_<stage>_<job> name) so uploadToAzure.yml's "Download nupkgs" step(s) can reference this
# artifact by a name that's guaranteed stable, instead of needing to match an undocumented
# naming convention. uploadToAzure.yml must download this artifact for these packages to reach
# the "globaltool/" folder in blob storage -- see its "Download global tool nupkgs" step.

parameters:
- name: OfficialBuild
type: boolean
default: true
- name: Rids
type: object

jobs:
- job: build_globaltool_pointer
displayName: 'Global tool pointer package'
# glbtool_rid is a single job definition that runs parallel matrix legs (one per RID);
# depending on its job name waits for every leg to finish, not just one.
dependsOn: glbtool_rid
condition: succeeded()
pool:
type: windows

variables:
- name: ob_artifactBaseName
value: drop_nupkg_build_globaltool_pointer
- name: ps_official_build
value: ${{ parameters.OfficialBuild }}
- name: nugetMultiFeedWarnLevel
value: none
- name: NugetSecurityAnalysisWarningLevel
value: none
- name: skipNugetSecurityAnalysis
value: true
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)\ONEBRANCH_ARTIFACT'
- name: ob_sdl_binskim_enabled
value: true
- name: ob_sdl_tsa_configFile
value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json
- name: ob_sdl_credscan_suppressionsFile
value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json
- group: mscodehub-feed-read-general
- group: mscodehub-feed-read-akv
- group: DotNetPrivateBuildAccess
- group: certificate_logical_to_actual

steps:
- checkout: self
clean: true
env:
ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase

- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
CreateJson: no

- template: /.pipelines/templates/shouldSign.yml@self

- template: /.pipelines/templates/cloneToOfficialPath.yml@self
parameters:
nativePathRoot: '$(Agent.TempDirectory)'

- ${{ each rid in parameters.Rids }}:
- download: current
artifact: globaltool-rid-${{ rid }}
displayName: 'Download globaltool-rid-${{ rid }}'
env:
ob_restore_phase: true

- template: /.pipelines/templates/install-dotnet.yml@self

- pwsh: |
Import-Module -Name '$(PowerShellRoot)\build.psm1'
Import-Module -Name '$(PowerShellRoot)\tools\packaging'
Find-DotNet
$rids = '${{ join(',', parameters.Rids) }}' -split ','
$ridOutputPath = Join-Path -Path '$(Pipeline.Workspace)' -ChildPath 'globaltool-multirid'
New-Item -Path $ridOutputPath -ItemType Directory -Force | Out-Null
# Gather each RID's nupkg (built and signed independently by its own parallel job) into one folder.
$missing = @()
foreach ($rid in $rids) {
$downloaded = Get-ChildItem -Path "$(Pipeline.Workspace)/globaltool-rid-$rid" -Filter "PowerShell.$rid.*.nupkg" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $downloaded) {
$missing += $rid
continue
}
Copy-Item -Path $downloaded.FullName -Destination $ridOutputPath -Force -Verbose
}
if ($missing) {
throw "Missing PowerShell global tool RID package(s): $($missing -join ', ')"
}
New-GlobalToolPointerNupkgSource -PackageVersion '$(Version)' -RuntimeIdentifiers $rids -SkipCGManifest
New-GlobalToolNupkgFromSource -PackageNuSpecPath "$global:GlobalToolNuSpecSourcePath" -PackageName "$global:GlobalToolPkgName" -DestinationPath $ridOutputPath
$global:GlobalToolNuSpecSourcePath = $null
$global:GlobalToolPkgName = $null
displayName: 'Create PowerShell global tool pointer package'
- task: onebranch.pipeline.signing@1
displayName: Sign PowerShell global tool RID nupkg files
inputs:
command: 'sign'
cp_code: '$(nuget_cert_id)'
files_to_sign: '**\*.nupkg'
search_root: '$(Pipeline.Workspace)\globaltool-multirid'

- pwsh: |
if (-not (Test-Path '$(ob_outputDirectory)')) {
New-Item -ItemType Directory -Path '$(ob_outputDirectory)' -Force
}
Write-Verbose -Verbose "Copying PowerShell global tool (RID-specific) packages to output directory"
$ridToolOutputPath = Join-Path -Path '$(Pipeline.Workspace)' -ChildPath 'globaltool-multirid'
Get-ChildItem -Path $ridToolOutputPath -Filter *.nupkg -Recurse | Copy-Item -Destination '$(ob_outputDirectory)' -Force -Verbose
displayName: Copy artifacts to output directory
- pwsh: |
Get-ChildItem -Path '$(ob_outputDirectory)' | Out-String | Write-Verbose -Verbose
displayName: List artifacts
185 changes: 185 additions & 0 deletions .pipelines/templates/job/globaltool-ref-assemblies.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Builds and signs the reference assemblies shared by the single-file IL nupkgs (built in
# nupkg.yml's build_nupkg job) and every RID-specific 'PowerShell' global tool package (built in
# job/globaltool-rid-job.yml). This used to run inline inside build_nupkg, which forced every
# consumer to wait for build_nupkg's full, long, sequential job before it could even start.
# Extracting it into its own small job lets build_nupkg and all 8 per-RID global tool jobs
# depend on just this one job and then run concurrently afterward.
#
# OneBranch pipelines don't allow the 'publish'/PublishPipelineArtifact step -- OneBranch
# automatically publishes each job's ob_outputDirectory as that job's own artifact at the end of
# the job (named via ob_artifactBaseName, same pattern as packaging/windows/package.yml's
# ob_artifactBaseName + sign.yml's matching 'download: current'). So the signed ref assemblies
# are copied into ob_outputDirectory here instead of being 'published' explicitly.

jobs:
- job: build_ref_assemblies
displayName: 'Build reference assemblies'
condition: succeeded()
pool:
type: windows

variables:
- name: ob_artifactBaseName
value: GlobalToolRefAssembly
- name: nugetMultiFeedWarnLevel
value: none
- name: NugetSecurityAnalysisWarningLevel
value: none
- name: skipNugetSecurityAnalysis
value: true
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)\ONEBRANCH_ARTIFACT'
- name: ob_sdl_binskim_enabled
value: true
- name: ob_sdl_tsa_configFile
value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json
- name: ob_sdl_credscan_suppressionsFile
value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json
- group: mscodehub-feed-read-general
- group: mscodehub-feed-read-akv
- group: DotNetPrivateBuildAccess
- group: certificate_logical_to_actual

steps:
- checkout: self
clean: true
env:
ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase

- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
CreateJson: no

- template: /.pipelines/templates/shouldSign.yml@self

- template: /.pipelines/templates/cloneToOfficialPath.yml@self
parameters:
nativePathRoot: '$(Agent.TempDirectory)'

- template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self
parameters:
repoRoot: $(PowerShellRoot)

- template: /.pipelines/templates/install-dotnet.yml@self

- pwsh: |
Set-Location -Path '$(PowerShellRoot)'
Import-Module "$(PowerShellRoot)/build.psm1" -Force
# Locates a project's generated reference assembly (obj/.../refint/<name>.dll) or XML doc
# comment file (bin/.../<name>.xml) by searching recursively instead of assuming a fixed
# "obj/Release/net11.0/refint/<name>.dll" path. Different SDK versions can insert an extra
# path segment (e.g. a RID folder) between the TFM and "refint" for a project built as
# part of a RID-specific publish graph, which made the previous hardcoded path brittle.
# For .dll lookups, only the immediate parent folder is required to be named "refint";
# otherwise this just returns the first/only match under $SearchRoot.
function Find-GeneratedFile {
param(
[Parameter(Mandatory)] [string] $SearchRoot,
[Parameter(Mandatory)] [string] $FileName,
[string] $RequiredParentFolderName
)
if (-not (Test-Path $SearchRoot)) {
return $null
}
$candidates = Get-ChildItem -Path $SearchRoot -Filter $FileName -Recurse -File -ErrorAction SilentlyContinue
if ($RequiredParentFolderName) {
$candidates = $candidates | Where-Object { $_.Directory.Name -eq $RequiredParentFolderName }
}
return $candidates | Select-Object -First 1
}
$sharedModules = @('Microsoft.PowerShell.Commands.Management',
'Microsoft.PowerShell.Commands.Utility',
'Microsoft.PowerShell.ConsoleHost',
'Microsoft.PowerShell.Security',
'System.Management.Automation'
)
$winOnlyModules = @('Microsoft.Management.Infrastructure.CimCmdlets',
'Microsoft.PowerShell.Commands.Diagnostics',
'Microsoft.PowerShell.CoreCLR.Eventing',
'Microsoft.WSMan.Management',
'Microsoft.WSMan.Runtime'
)
$refAssemblyFolder = Join-Path '$(System.ArtifactsDirectory)' 'RefAssembly'
$null = New-Item -Path $refAssemblyFolder -Force -Verbose -Type Directory
Start-PSBuild -Clean -Runtime linux-x64 -Configuration Release -ReleaseTag $(ReleaseTagVar)
$sharedModules | Foreach-Object {
$moduleName = $_
$objRoot = "$(PowerShellRoot)\src\$moduleName\obj\Release"
$refFile = Find-GeneratedFile -SearchRoot $objRoot -FileName "$moduleName.dll" -RequiredParentFolderName 'refint'
if (-not $refFile) {
Write-Verbose -Verbose "Reference assembly for $moduleName not found under $objRoot. Dumping obj tree for diagnostics:"
Get-ChildItem -Path $objRoot -Recurse -File -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName | Write-Verbose -Verbose
throw "Reference assembly for $moduleName was not found under $objRoot (expected a 'refint\$moduleName.dll')."
}
Write-Verbose -Verbose "RefAssembly: $($refFile.FullName)"
Copy-Item -Path $refFile.FullName -Destination "$refAssemblyFolder\$moduleName.dll" -Verbose
$binRoot = "$(PowerShellRoot)\src\$moduleName\bin\Release"
$refDoc = Find-GeneratedFile -SearchRoot $binRoot -FileName "$moduleName.xml"
if (-not $refDoc) {
Write-Warning "$moduleName.xml not found under $binRoot"
Get-ChildItem -Path $binRoot -Recurse -File -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName | Out-String | Write-Verbose -Verbose
}
else {
Copy-Item -Path $refDoc.FullName -Destination "$refAssemblyFolder\$moduleName.xml" -Verbose
}
}
Start-PSBuild -Clean -Runtime win7-x64 -Configuration Release -ReleaseTag $(ReleaseTagVar)
$winOnlyModules | Foreach-Object {
$moduleName = $_
$objRoot = "$(PowerShellRoot)\src\$moduleName\obj\Release"
$refFile = Find-GeneratedFile -SearchRoot $objRoot -FileName "$moduleName.dll" -RequiredParentFolderName 'refint'
if (-not $refFile) {
Write-Verbose -Verbose "Reference assembly for $moduleName not found under $objRoot. Dumping obj tree for diagnostics:"
Get-ChildItem -Path $objRoot -Recurse -File -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName | Write-Verbose -Verbose
throw "Reference assembly for $moduleName was not found under $objRoot (expected a 'refint\$moduleName.dll')."
}
Write-Verbose -Verbose "RefAssembly: $($refFile.FullName)"
Copy-Item -Path $refFile.FullName -Destination "$refAssemblyFolder\$moduleName.dll" -Verbose
$binRoot = "$(PowerShellRoot)\src\$moduleName\bin\Release"
$refDoc = Find-GeneratedFile -SearchRoot $binRoot -FileName "$moduleName.xml"
if (-not $refDoc) {
Write-Warning "$moduleName.xml not found under $binRoot"
Get-ChildItem -Path $binRoot -Recurse -File -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName | Out-String | Write-Verbose -Verbose
}
else {
Copy-Item -Path $refDoc.FullName -Destination "$refAssemblyFolder\$moduleName.xml" -Verbose
}
}
Get-ChildItem $refAssemblyFolder -Recurse | Out-String | Write-Verbose -Verbose
displayName: Build reference assemblies
env:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)
- task: onebranch.pipeline.signing@1
displayName: Sign ref assemblies
inputs:
command: 'sign'
signing_profile: external_distribution
files_to_sign: '**\*.dll'
search_root: '$(System.ArtifactsDirectory)\RefAssembly'

# OneBranch disallows the 'publish'/PublishPipelineArtifact step ("Onebranch automatically
# upload binaries at the end of the job"). Copy into ob_outputDirectory instead; OneBranch
# publishes its contents as this job's own artifact, named via ob_artifactBaseName above.
- pwsh: |
if (-not (Test-Path '$(ob_outputDirectory)')) {
New-Item -ItemType Directory -Path '$(ob_outputDirectory)' -Force
}
Copy-Item -Path '$(System.ArtifactsDirectory)\RefAssembly\*' -Destination '$(ob_outputDirectory)' -Recurse -Force -Verbose
displayName: 'Copy GlobalToolRefAssembly to output directory'
Loading
Loading