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
76 changes: 25 additions & 51 deletions build.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -2234,43 +2234,6 @@ function Get-RedHatPackageManager {
}
}

function Install-GlobalGem {
param(
[Parameter()]
[string]
$Sudo = "",

[Parameter(Mandatory)]
[string]
$GemName,

[Parameter(Mandatory)]
[string]
$GemVersion
)
try {
# We cannot guess if the user wants to run gem install as root on linux and windows,
# but macOs usually requires sudo
$gemsudo = ''
if($environment.IsMacOS -or $env:TF_BUILD -or $env:GITHUB_ACTIONS) {
$gemsudo = $sudo
}

Start-NativeExecution ([ScriptBlock]::Create("$gemsudo gem install $GemName -v $GemVersion --no-document"))

} catch {
Write-Warning "Installation of gem $GemName $GemVersion failed! Must resolve manually."
$logs = Get-ChildItem "/var/lib/gems/*/extensions/x86_64-linux/*/$GemName-*/gem_make.out" | Select-Object -ExpandProperty FullName
foreach ($log in $logs) {
Write-Verbose "Contents of: $log" -Verbose
Get-Content -Raw -Path $log -ErrorAction Ignore | ForEach-Object { Write-Verbose $_ -Verbose }
Write-Verbose "END Contents of: $log" -Verbose
}

throw
}
}

function Start-PSBootstrap {
[CmdletBinding()]
param(
Expand All @@ -2282,7 +2245,7 @@ function Start-PSBootstrap {
[switch]$BuildLinuxArm,
[switch]$Force,
[Parameter(Mandatory = $true)]
# Package: Install dependencies for packaging tools (fpm, rpmbuild, WiX)
# Package: Install dependencies for packaging tools (rpmbuild, dpkg-deb, pkgbuild, WiX)
# DotNet: Install the .NET SDK
# Both: Package and DotNet scenarios
# Tools: Install .NET global tools (e.g., dotnet-format)
Expand Down Expand Up @@ -2321,7 +2284,9 @@ function Start-PSBootstrap {
elseif ($environment.IsUbuntu18) { $Deps += "libicu60"}

# Packaging tools
if ($Scenario -eq 'Both' -or $Scenario -eq 'Package') { $Deps += "ruby-dev", "groff", "libffi-dev", "rpm", "g++", "make" }
# Note: ruby-dev, libffi-dev, g++, and make are no longer needed for DEB packaging
# DEB packages now use native dpkg-deb (pre-installed)
if ($Scenario -eq 'Both' -or $Scenario -eq 'Package') { $Deps += "groff", "rpm" }

# Install dependencies
# change the fontend from apt-get to noninteractive
Expand All @@ -2345,7 +2310,9 @@ function Start-PSBootstrap {
$Deps += "libicu", "openssl-libs"

# Packaging tools
if ($Scenario -eq 'Both' -or $Scenario -eq 'Package') { $Deps += "ruby-devel", "rpm-build", "groff", 'libffi-devel', "gcc-c++" }
# Note: ruby-devel and libffi-devel are no longer needed
# RPM packages use rpmbuild, DEB packages use dpkg-deb
if ($Scenario -eq 'Both' -or $Scenario -eq 'Package') { $Deps += "rpm-build", "groff" }

$PackageManager = Get-RedHatPackageManager

Expand All @@ -2366,7 +2333,8 @@ function Start-PSBootstrap {
$Deps += "wget"

# Packaging tools
if ($Scenario -eq 'Both' -or $Scenario -eq 'Package') { $Deps += "ruby-devel", "rpmbuild", "groff", 'libffi-devel', "gcc" }
# Note: ruby-devel and libffi-devel are no longer needed for packaging
if ($Scenario -eq 'Both' -or $Scenario -eq 'Package') { $Deps += "rpmbuild", "groff" }

$PackageManager = "zypper --non-interactive install"
$baseCommand = "$sudo $PackageManager"
Expand Down Expand Up @@ -2405,17 +2373,7 @@ function Start-PSBootstrap {
}
}

# Install [fpm](https://github.com/jordansissel/fpm)
# Note: fpm is now only needed for DEB and macOS packages; RPM packages use rpmbuild directly
if ($Scenario -in 'All', 'Both', 'Package') {
# Install fpm on Debian-based systems, macOS, and Mariner (where DEB packages are built)
if (($environment.IsLinux -and ($environment.IsDebianFamily -or $environment.IsMariner)) -or $environment.IsMacOS) {
Install-GlobalGem -Sudo $sudo -GemName "dotenv" -GemVersion "2.8.1"
Install-GlobalGem -Sudo $sudo -GemName "ffi" -GemVersion "1.16.3"
Install-GlobalGem -Sudo $sudo -GemName "fpm" -GemVersion "1.15.1"
Install-GlobalGem -Sudo $sudo -GemName "rexml" -GemVersion "3.2.5"
}

# For RPM-based systems, ensure rpmbuild is available
if ($environment.IsLinux -and ($environment.IsRedHatFamily -or $environment.IsSUSEFamily -or $environment.IsMariner)) {
Write-Verbose -Verbose "Checking for rpmbuild..."
Expand All @@ -2424,6 +2382,22 @@ function Start-PSBootstrap {
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo $PackageManager install -y rpm-build")) -IgnoreExitcode
}
}

# For Debian-based systems and Mariner, ensure dpkg-deb is available
if ($environment.IsLinux -and ($environment.IsDebianFamily -or $environment.IsMariner)) {
Write-Verbose -Verbose "Checking for dpkg-deb..."
if (!(Get-Command dpkg-deb -ErrorAction SilentlyContinue)) {
Write-Warning "dpkg-deb not found. Installing dpkg package..."
if ($environment.IsMariner) {
# For Mariner (Azure Linux), install the extended repo first to access dpkg.
Write-Verbose -Verbose "Installing azurelinux-repos-extended for Mariner..."
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo $PackageManager install -y azurelinux-repos-extended")) -IgnoreExitcode
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo $PackageManager install -y dpkg")) -IgnoreExitcode
} else {
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo apt-get install -y dpkg")) -IgnoreExitcode
}
}
}
}
}

Expand Down
48 changes: 37 additions & 11 deletions test/packaging/linux/package-validation.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ Describe "Linux Package Name Validation" {
It "Should have valid RPM package names" {
$rpmPackages = Get-ChildItem -Path $artifactsDir -Recurse -Filter *.rpm -ErrorAction SilentlyContinue

if ($rpmPackages.Count -eq 0) {
Set-ItResult -Skipped -Because "No RPM packages found in artifacts directory"
return
}
$rpmPackages.Count | Should -BeGreaterThan 0 -Because "At least one RPM package should exist in the artifacts directory"

$invalidPackages = @()
# Regex pattern for valid RPM package names.
Expand All @@ -49,19 +46,50 @@ Describe "Linux Package Name Validation" {
if ($invalidPackages.Count -gt 0) {
throw ($invalidPackages | Out-String)
}
}
}

Context "DEB Package Names" {
It "Should have valid DEB package names" {
$debPackages = Get-ChildItem -Path $artifactsDir -Recurse -Filter *.deb -ErrorAction SilentlyContinue

$debPackages.Count | Should -BeGreaterThan 0 -Because "At least one DEB package should exist in the artifacts directory"

$invalidPackages = @()
# Regex pattern for valid DEB package names.
# Valid examples:
# - powershell-preview_7.6.0-preview.6-1.deb_amd64.deb
# - powershell-lts_7.4.13-1.deb_amd64.deb
# - powershell_7.4.13-1.deb_amd64.deb
# Breakdown:
# ^powershell : Starts with 'powershell'
# (-preview|-lts)? : Optionally '-preview' or '-lts'
# _\d+\.\d+\.\d+ : Underscore followed by version number (e.g., _7.6.0)
# (-[a-z]+\.\d+)? : Optional dash, letters, dot, and digits (e.g., -preview.6)
# -1 : Literal '-1'
# \.deb_ : Literal '.deb_'
# (amd64|arm64) : Architecture
# \.deb$ : File extension
$debPackageNamePattern = '^powershell(-preview|-lts)?_\d+\.\d+\.\d+(-[a-z]+\.\d+)?-1\.deb_(amd64|arm64)\.deb$'
Comment on lines +61 to +73
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DEB package name pattern is incorrect and doesn't match the actual filenames generated by New-NativeDeb. The pattern expects -1\.deb_ (line 70, 73), but the actual iteration can be "1.deb" OR distribution-specific like "1.ubuntu.20.04" (see packaging.psm1:1125 where Iteration is appended with distribution). The generated filename format is ${Name}_${Version}-${Iteration}_${HostArchitecture}.deb (packaging.psm1:1898), which produces names like powershell_7.4.13-1.ubuntu.20.04_amd64.deb, not powershell_7.4.13-1.deb_amd64.deb. The pattern should be: ^powershell(-preview|-lts)?_\d+\.\d+\.\d+(-[a-z]+\.\d+)?-\d+(\.[a-z]+\.\d+(\.\d+)?)?_(amd64|arm64)\.deb$ to match both "1.deb" and "1.ubuntu.20.04" style iterations.

Suggested change
# - powershell-preview_7.6.0-preview.6-1.deb_amd64.deb
# - powershell-lts_7.4.13-1.deb_amd64.deb
# - powershell_7.4.13-1.deb_amd64.deb
# Breakdown:
# ^powershell : Starts with 'powershell'
# (-preview|-lts)? : Optionally '-preview' or '-lts'
# _\d+\.\d+\.\d+ : Underscore followed by version number (e.g., _7.6.0)
# (-[a-z]+\.\d+)? : Optional dash, letters, dot, and digits (e.g., -preview.6)
# -1 : Literal '-1'
# \.deb_ : Literal '.deb_'
# (amd64|arm64) : Architecture
# \.deb$ : File extension
$debPackageNamePattern = '^powershell(-preview|-lts)?_\d+\.\d+\.\d+(-[a-z]+\.\d+)?-1\.deb_(amd64|arm64)\.deb$'
# - powershell-preview_7.6.0-preview.6-1.ubuntu.20.04_amd64.deb
# - powershell-lts_7.4.13-1_amd64.deb
# - powershell_7.4.13-1.ubuntu.20.04_amd64.deb
# Breakdown:
# ^powershell : Starts with 'powershell'
# (-preview|-lts)? : Optionally '-preview' or '-lts'
# _\d+\.\d+\.\d+ : Underscore followed by version number (e.g., _7.6.0)
# (-[a-z]+\.\d+)? : Optional dash, letters, dot, and digits (e.g., -preview.6)
# -\d+ : Dash followed by numeric iteration (e.g., -1)
# (\.[a-z]+\.\d+(\.\d+)?)? : Optional distribution suffix (e.g., .ubuntu.20.04)
# _(amd64|arm64) : Underscore followed by architecture
# \.deb$ : File extension
$debPackageNamePattern = '^powershell(-preview|-lts)?_\d+\.\d+\.\d+(-[a-z]+\.\d+)?-\d+(\.[a-z]+\.\d+(\.\d+)?)?_(amd64|arm64)\.deb$'

Copilot uses AI. Check for mistakes.
Comment on lines +61 to +73
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example filenames in the comments are incorrect and inconsistent with the actual DEB package naming format. The examples show filenames like powershell-preview_7.6.0-preview.6-1.deb_amd64.deb, but based on the New-NativeDeb implementation (packaging.psm1:1898), the actual format is powershell-preview_7.6.0-preview.6-1_amd64.deb. The examples should be updated to reflect the correct format.

Suggested change
# - powershell-preview_7.6.0-preview.6-1.deb_amd64.deb
# - powershell-lts_7.4.13-1.deb_amd64.deb
# - powershell_7.4.13-1.deb_amd64.deb
# Breakdown:
# ^powershell : Starts with 'powershell'
# (-preview|-lts)? : Optionally '-preview' or '-lts'
# _\d+\.\d+\.\d+ : Underscore followed by version number (e.g., _7.6.0)
# (-[a-z]+\.\d+)? : Optional dash, letters, dot, and digits (e.g., -preview.6)
# -1 : Literal '-1'
# \.deb_ : Literal '.deb_'
# (amd64|arm64) : Architecture
# \.deb$ : File extension
$debPackageNamePattern = '^powershell(-preview|-lts)?_\d+\.\d+\.\d+(-[a-z]+\.\d+)?-1\.deb_(amd64|arm64)\.deb$'
# - powershell-preview_7.6.0-preview.6-1_amd64.deb
# - powershell-lts_7.4.13-1_amd64.deb
# - powershell_7.4.13-1_amd64.deb
# Breakdown:
# ^powershell : Starts with 'powershell'
# (-preview|-lts)? : Optionally '-preview' or '-lts'
# _\d+\.\d+\.\d+ : Underscore followed by version number (e.g., _7.6.0)
# (-[a-z]+\.\d+)? : Optional dash, letters, dot, and digits (e.g., -preview.6)
# -1 : Literal '-1'
# _ : Underscore separating version/build from architecture
# (amd64|arm64) : Architecture
# \.deb$ : File extension
$debPackageNamePattern = '^powershell(-preview|-lts)?_\d+\.\d+\.\d+(-[a-z]+\.\d+)?-1_(amd64|arm64)\.deb$'

Copilot uses AI. Check for mistakes.

foreach ($package in $debPackages) {
if ($package.Name -notmatch $debPackageNamePattern) {
$invalidPackages += "$($package.Name) is not a valid DEB package name"
Write-Warning "$($package.Name) is not a valid DEB package name"
}
}

$rpmPackages.Count | Should -BeGreaterThan 0
if ($invalidPackages.Count -gt 0) {
throw ($invalidPackages | Out-String)
}
}
}

Context "Tar.Gz Package Names" {
It "Should have valid tar.gz package names" {
$tarPackages = Get-ChildItem -Path $artifactsDir -Recurse -Filter *.tar.gz -ErrorAction SilentlyContinue

if ($tarPackages.Count -eq 0) {
Set-ItResult -Skipped -Because "No tar.gz packages found in artifacts directory"
return
}
$tarPackages.Count | Should -BeGreaterThan 0 -Because "At least one tar.gz package should exist in the artifacts directory"

$invalidPackages = @()
foreach ($package in $tarPackages) {
Expand All @@ -76,8 +104,6 @@ Describe "Linux Package Name Validation" {
if ($invalidPackages.Count -gt 0) {
throw ($invalidPackages | Out-String)
}

$tarPackages.Count | Should -BeGreaterThan 0
}
}

Expand Down
Loading