Skip to content

Commit e7bf562

Browse files
authored
Improve ADO package build and validation across platforms (PowerShell#26398)
1 parent 3953976 commit e7bf562

File tree

5 files changed

+116
-74
lines changed

5 files changed

+116
-74
lines changed

.github/workflows/macos-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ jobs:
205205
}
206206
Import-Module Pester
207207
$pesterConfig = New-PesterConfiguration
208-
$pesterConfig.Run.Path = './tools/packaging/releaseTests/macOSPackage.tests.ps1'
208+
$pesterConfig.Run.Path = './test/packaging/macos/package-validation.tests.ps1'
209209
$pesterConfig.Run.PassThru = $true
210210
$pesterConfig.Output.Verbosity = 'Detailed'
211211
$pesterConfig.TestResult.Enabled = $true

.pipelines/templates/mac-package-build.yml

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,25 @@ jobs:
116116
117117
Start-PSPackage -Type osxpkg -SkipReleaseChecks -MacOSRuntime $macosRuntime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath -LTS:$LTS
118118
$pkgNameFilter = "powershell-*$macosRuntime.pkg"
119-
$pkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $pkgNameFilter -Recurse -File | Select-Object -ExpandProperty FullName
120-
Write-Host "##vso[artifact.upload containerfolder=macos-pkgs;artifactname=macos-pkgs]$pkgPath"
119+
Write-Verbose -Verbose "Looking for pkg packages with filter: $pkgNameFilter in '$(Pipeline.Workspace)' to upload..."
120+
$pkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $pkgNameFilter -Recurse -File
121+
122+
foreach($p in $pkgPath) {
123+
$file = $p.FullName
124+
Write-Verbose -verbose "Uploading $file to macos-pkgs"
125+
Write-Host "##vso[artifact.upload containerfolder=macos-pkgs;artifactname=macos-pkgs]$file"
126+
}
121127
122128
Start-PSPackage -Type tar -SkipReleaseChecks -MacOSRuntime $macosRuntime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath -LTS:$LTS
123129
$tarPkgNameFilter = "powershell-*$macosRuntime.tar.gz"
124-
$tarPkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $tarPkgNameFilter -Recurse -File | Select-Object -ExpandProperty FullName
125-
Write-Host "##vso[artifact.upload containerfolder=macos-pkgs;artifactname=macos-pkgs]$tarPkgPath"
130+
Write-Verbose -Verbose "Looking for tar packages with filter: $tarPkgNameFilter in '$(Pipeline.Workspace)' to upload..."
131+
$tarPkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $tarPkgNameFilter -Recurse -File
132+
133+
foreach($t in $tarPkgPath) {
134+
$file = $t.FullName
135+
Write-Verbose -verbose "Uploading $file to macos-pkgs"
136+
Write-Host "##vso[artifact.upload containerfolder=macos-pkgs;artifactname=macos-pkgs]$file"
137+
}
126138
127139
displayName: 'Package ${{ parameters.buildArchitecture}}'
128140
env:
@@ -195,14 +207,14 @@ jobs:
195207
196208
- pwsh: |
197209
$signedPkg = Get-ChildItem -Path $(Pipeline.Workspace) -Filter "*osx*.zip" -File
198-
210+
199211
$signedPkg | ForEach-Object {
200212
Write-Verbose -Verbose "Signed package zip: $_"
201-
213+
202214
if (-not (Test-Path $_)) {
203215
throw "Package not found: $_"
204216
}
205-
217+
206218
if (-not (Test-Path $(ob_outputDirectory))) {
207219
$null = New-Item -Path $(ob_outputDirectory) -ItemType Directory
208220
}

build.psm1

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2399,17 +2399,22 @@ function Start-PSBootstrap {
23992399
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo $PackageManager install -y rpm-build")) -IgnoreExitcode
24002400
}
24012401
}
2402-
2402+
24032403
# For Debian-based systems and Mariner, ensure dpkg-deb is available
24042404
if ($environment.IsLinux -and ($environment.IsDebianFamily -or $environment.IsMariner)) {
24052405
Write-Verbose -Verbose "Checking for dpkg-deb..."
24062406
if (!(Get-Command dpkg-deb -ErrorAction SilentlyContinue)) {
24072407
Write-Warning "dpkg-deb not found. Installing dpkg package..."
24082408
if ($environment.IsMariner) {
24092409
# For Mariner (Azure Linux), install the extended repo first to access dpkg.
2410+
Write-Verbose -verbose "BEGIN: /etc/os-release content:"
2411+
Get-Content /etc/os-release | Write-Verbose -verbose
2412+
Write-Verbose -verbose "END: /etc/os-release content"
2413+
24102414
Write-Verbose -Verbose "Installing azurelinux-repos-extended for Mariner..."
2411-
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo $PackageManager install -y azurelinux-repos-extended")) -IgnoreExitcode
2412-
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo $PackageManager install -y dpkg")) -IgnoreExitcode
2415+
2416+
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo $PackageManager azurelinux-repos-extended")) -IgnoreExitcode -Verbose
2417+
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo $PackageManager dpkg")) -IgnoreExitcode -Verbose
24132418
} else {
24142419
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo apt-get install -y dpkg")) -IgnoreExitcode
24152420
}

tools/packaging/releaseTests/macOSPackage.tests.ps1 renamed to test/packaging/macos/package-validation.tests.ps1

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,54 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
14
Describe "Verify macOS Package" {
25
BeforeAll {
36
Write-Verbose "In Describe BeforeAll" -Verbose
47
Import-Module $PSScriptRoot/../../../build.psm1
5-
8+
69
# Find the macOS package
710
$packagePath = $env:PACKAGE_FOLDER
811
if (-not $packagePath) {
912
$packagePath = Get-Location
1013
}
11-
14+
1215
Write-Verbose "Looking for package in: $packagePath" -Verbose
1316
$package = Get-ChildItem -Path $packagePath -Filter "*.pkg" -ErrorAction SilentlyContinue | Select-Object -First 1
14-
17+
1518
if (-not $package) {
1619
Write-Warning "No .pkg file found in $packagePath"
1720
} else {
1821
Write-Verbose "Found package: $($package.FullName)" -Verbose
1922
}
20-
23+
2124
# Set up test directories
2225
$script:package = $package
2326
$script:expandDir = $null
2427
$script:payloadDir = $null
2528
$script:extractedFiles = @()
26-
29+
2730
if ($package) {
2831
# Use TestDrive for temporary directories - pkgutil will create the expand directory
2932
$script:expandDir = Join-Path "TestDrive:" -ChildPath "package-contents-test"
3033
$expandDirResolved = (Resolve-Path "TestDrive:").ProviderPath
3134
$script:expandDir = Join-Path $expandDirResolved -ChildPath "package-contents-test"
32-
35+
3336
Write-Verbose "Expanding package to: $($script:expandDir)" -Verbose
3437
# pkgutil will create the directory itself, so don't pre-create it
3538
Start-NativeExecution {
3639
pkgutil --expand $package.FullName $script:expandDir
3740
}
38-
41+
3942
# Extract the payload to verify files
4043
$script:payloadDir = Join-Path "TestDrive:" -ChildPath "package-payload-test"
4144
$payloadDirResolved = (Resolve-Path "TestDrive:").ProviderPath
4245
$script:payloadDir = Join-Path $payloadDirResolved -ChildPath "package-payload-test"
43-
46+
4447
# Create payload directory since cpio needs it
4548
if (-not (Test-Path $script:payloadDir)) {
4649
$null = New-Item -ItemType Directory -Path $script:payloadDir -Force
4750
}
48-
51+
4952
$componentPkg = Get-ChildItem -Path $script:expandDir -Filter "*.pkg" -Recurse | Select-Object -First 1
5053
if ($componentPkg) {
5154
Write-Verbose "Extracting payload from: $($componentPkg.FullName)" -Verbose
@@ -57,40 +60,60 @@ Describe "Verify macOS Package" {
5760
Pop-Location
5861
}
5962
}
60-
63+
6164
# Get all extracted files for verification
6265
$script:extractedFiles = Get-ChildItem -Path $script:payloadDir -Recurse -ErrorAction SilentlyContinue
6366
Write-Verbose "Extracted $($script:extractedFiles.Count) files" -Verbose
6467
}
6568
}
66-
69+
6770
AfterAll {
6871
# TestDrive automatically cleans up, but we can ensure cleanup happens
6972
# No manual cleanup needed as TestDrive handles it
7073
}
71-
74+
7275
Context "Package existence and structure" {
7376
It "Package file should exist" {
7477
$script:package | Should -Not -BeNullOrEmpty -Because "A .pkg file should be created"
7578
$script:package.Extension | Should -Be ".pkg"
7679
}
77-
80+
81+
It "Package name should follow correct naming convention" {
82+
$script:package | Should -Not -BeNullOrEmpty
83+
84+
# Regex pattern for valid macOS PKG package names.
85+
# Valid examples:
86+
# - powershell-7.4.13-osx-x64.pkg (Intel x64 - note: x64 with hyphens for compatibility)
87+
# - powershell-7.4.13-osx-arm64.pkg (Apple Silicon)
88+
# - powershell-preview-7.6.0-preview.6-osx-x64.pkg
89+
# - powershell-lts-7.4.13-osx-arm64.pkg
90+
$pkgPackageNamePattern = '^powershell(-preview|-lts)?-\d+\.\d+\.\d+(-[a-z]+\.\d+)?-osx-(x64|arm64)\.pkg$'
91+
92+
$script:package.Name | Should -Match $pkgPackageNamePattern -Because "Package name should follow the standard naming convention"
93+
}
94+
95+
It "Package name should NOT use x86_64 with underscores" {
96+
$script:package | Should -Not -BeNullOrEmpty
97+
98+
$script:package.Name | Should -Not -Match 'x86_64' -Because "Package should use 'x64' not 'x86_64' (with underscores) for compatibility"
99+
}
100+
78101
It "Package should expand successfully" {
79102
$script:expandDir | Should -Exist
80103
Get-ChildItem -Path $script:expandDir | Should -Not -BeNullOrEmpty
81104
}
82-
105+
83106
It "Package should have a component package" {
84107
$componentPkg = Get-ChildItem -Path $script:expandDir -Filter "*.pkg" -Recurse -ErrorAction SilentlyContinue
85108
$componentPkg | Should -Not -BeNullOrEmpty -Because "Package should contain a component.pkg"
86109
}
87-
110+
88111
It "Payload should extract successfully" {
89112
$script:payloadDir | Should -Exist
90113
$script:extractedFiles | Should -Not -BeNullOrEmpty -Because "Package payload should contain files"
91114
}
92115
}
93-
116+
94117
Context "Required files in package" {
95118
BeforeAll {
96119
$expectedFilePatterns = @{
@@ -99,31 +122,31 @@ Describe "Verify macOS Package" {
99122
"Man page" = "usr/local/share/man/man1/pwsh*.gz"
100123
"Launcher application plist" = "Applications/PowerShell*.app/Contents/Info.plist"
101124
}
102-
125+
103126
$testCases = @()
104127
foreach ($key in $expectedFilePatterns.Keys) {
105128
$testCases += @{
106129
Description = $key
107130
Pattern = $expectedFilePatterns[$key]
108131
}
109132
}
110-
133+
111134
$script:testCases = $testCases
112135
}
113-
136+
114137
It "Should contain <Description>" -TestCases $script:testCases {
115138
param($Description, $Pattern)
116-
139+
117140
$found = $script:extractedFiles | Where-Object { $_.FullName -like "*$Pattern*" }
118141
$found | Should -Not -BeNullOrEmpty -Because "$Description should exist in the package at path matching '$Pattern'"
119142
}
120143
}
121-
144+
122145
Context "PowerShell binary verification" {
123146
It "PowerShell executable should be executable" {
124147
$pwshBinary = $script:extractedFiles | Where-Object { $_.FullName -like "*/pwsh" -and $_.FullName -like "*/microsoft/powershell/*" }
125148
$pwshBinary | Should -Not -BeNullOrEmpty
126-
149+
127150
# Check if file has executable permissions (on Unix-like systems)
128151
if ($IsLinux -or $IsMacOS) {
129152
$permissions = (Get-Item $pwshBinary[0].FullName).UnixFileMode
@@ -132,27 +155,27 @@ Describe "Verify macOS Package" {
132155
}
133156
}
134157
}
135-
158+
136159
Context "Launcher application" {
137160
It "Launcher app should have proper bundle structure" {
138161
$plistFile = $script:extractedFiles | Where-Object { $_.FullName -like "*PowerShell*.app/Contents/Info.plist" }
139162
$plistFile | Should -Not -BeNullOrEmpty
140-
163+
141164
# Verify the bundle has required components
142165
$appPath = Split-Path (Split-Path $plistFile[0].FullName -Parent) -Parent
143166
$macOSDir = Join-Path $appPath "Contents/MacOS"
144167
$resourcesDir = Join-Path $appPath "Contents/Resources"
145-
168+
146169
Test-Path $macOSDir | Should -Be $true -Because "App bundle should have Contents/MacOS directory"
147170
Test-Path $resourcesDir | Should -Be $true -Because "App bundle should have Contents/Resources directory"
148171
}
149-
172+
150173
It "Launcher script should exist and be executable" {
151-
$launcherScript = $script:extractedFiles | Where-Object {
152-
$_.FullName -like "*PowerShell*.app/Contents/MacOS/PowerShell.sh"
174+
$launcherScript = $script:extractedFiles | Where-Object {
175+
$_.FullName -like "*PowerShell*.app/Contents/MacOS/PowerShell.sh"
153176
}
154177
$launcherScript | Should -Not -BeNullOrEmpty -Because "Launcher script should exist"
155-
178+
156179
if ($IsLinux -or $IsMacOS) {
157180
$permissions = (Get-Item $launcherScript[0].FullName).UnixFileMode
158181
$permissions.ToString() | Should -Match 'x' -Because "Launcher script should have execute permissions"

0 commit comments

Comments
 (0)