Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .pipelines/templates/release-validate-packagenames.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
- pwsh: |
$message = @()
Get-ChildItem $(System.ArtifactsDirectory)\* -recurse -filter *.rpm | ForEach-Object {
if($_.Name -notmatch 'powershell\-(preview-|lts-)?\d+\.\d+\.\d+(_[a-z]*\.\d+)?-1.(rh|cm).(x86_64|aarch64)\.rpm')
if($_.Name -notmatch '^powershell-(preview-|lts-)?\d+\.\d+\.\d+(_[a-z]*\.\d+)?-1\.(preview\.\d+\.)?(rh|cm|azl4)\.(x86_64|aarch64)\.rpm$')
{
$messageInstance = "$($_.Name) is not a valid package name"
$message += $messageInstance
Expand Down
31 changes: 29 additions & 2 deletions test/packaging/linux/package-validation.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,37 @@ Describe "Linux Package Name Validation" {
}

Write-Verbose "Artifacts directory: $artifactsDir" -Verbose

# Keep this pattern aligned with the release validation pipeline.
$rpmPackageNamePattern = '^powershell-(preview-|lts-)?\d+\.\d+\.\d+(_[a-z]*\.\d+)?-1\.(preview\.\d+\.)?(rh|cm|azl4)\.(x86_64|aarch64)\.rpm$'
}

Context "RPM Package Names" {
It "Should accept the Azure Linux 4 <Architecture> package name" -TestCases @(
@{
Architecture = "x86_64"
Name = "powershell-preview-7.6.0_preview.6-1.azl4.x86_64.rpm"
}
@{
Architecture = "aarch64"
Name = "powershell-preview-7.6.0_preview.6-1.azl4.aarch64.rpm"
}
) {
param($Name)

$Name | Should -Match $rpmPackageNamePattern
}

It "Should reject malformed RPM package name <Name>" -TestCases @(
@{ Name = "prefix-powershell-preview-7.6.0_preview.6-1.azl4.x86_64.rpm" }
@{ Name = "powershell-preview-7.6.0_preview.6-1Xazl4.x86_64.rpm" }
@{ Name = "powershell-preview-7.6.0_preview.6-1.azl4.x86_64.rpm.backup" }
) {
param($Name)

$Name | Should -Not -Match $rpmPackageNamePattern
}

It "Should have valid RPM package names" {
$rpmPackages = Get-ChildItem -Path $artifactsDir -Recurse -Filter *.rpm -ErrorAction SilentlyContinue

Expand All @@ -32,9 +60,8 @@ Describe "Linux Package Name Validation" {
# (_[a-z]*\.\d+)? : Optional underscore, letters, dot, and digits (e.g., _alpha.1)
# -1\. : Literal '-1.'
# (preview\.\d+\.)? : Optional 'preview.' and digits, followed by a dot
# (rh|cm)\. : Either 'rh.' or 'cm.'
# (rh|cm|azl4)\. : RPM distribution suffix
# (x86_64|aarch64)\.rpm$ : Architecture and file extension
$rpmPackageNamePattern = 'powershell\-(preview-|lts-)?\d+\.\d+\.\d+(_[a-z]*\.\d+)?-1\.(preview\.\d+\.)?(rh|cm)\.(x86_64|aarch64)\.rpm'

foreach ($package in $rpmPackages) {
if ($package.Name -notmatch $rpmPackageNamePattern) {
Expand Down
153 changes: 153 additions & 0 deletions test/packaging/packaging.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,159 @@ Describe "Packaging Module Functions" {
}
}

Context "Azure Linux RPM packaging" {
BeforeAll {
$afterInstallScript = Join-Path $TestDrive "after-install.sh"
$afterRemoveScript = Join-Path $TestDrive "after-remove.sh"
"echo installed" | Set-Content -Path $afterInstallScript
"echo removed" | Set-Content -Path $afterRemoveScript
$linkInfo = & (Get-Module packaging) {
[LinkInfo] @{
Source = "/tmp/pwsh"
Destination = "/usr/bin/pwsh"
}
}
}

It "Should target Azure Linux 3 and 4 for framework-dependent RPMs" {
$distributions = & (Get-Module packaging) { $Script:RedhatFddDistributions }
$distributions | Should -Be @("cm", "azl4")
}

It "Should generate an Azure Linux 4 RPM file name for <HostArchitecture>" -TestCases @(
@{
HostArchitecture = "x86_64"
Expected = "powershell-preview-7.6.0_preview.6-1.azl4.x86_64.rpm"
}
@{
HostArchitecture = "aarch64"
Expected = "powershell-preview-7.6.0_preview.6-1.azl4.aarch64.rpm"
}
) {
param($HostArchitecture, $Expected)

Get-RpmPackageFileName `
-Name "powershell-preview" `
-Version "7.6.0-preview.6" `
-Iteration "1" `
-Distribution "azl4" `
-HostArchitecture $HostArchitecture |
Should -BeExactly $Expected
}

It "Should write the Azure Linux 4 RPM Release metadata for <HostArchitecture>" -TestCases @(
@{ HostArchitecture = "x86_64" }
@{ HostArchitecture = "aarch64" }
) {
param($HostArchitecture)

$spec = New-RpmSpec `
-Name "powershell-preview" `
-Version "7.6.0-preview.6" `
-Iteration "1" `
-Description "PowerShell test package" `
-Staging "/tmp/staging" `
-Destination "/opt/microsoft/powershell/7-preview" `
-ManGzipFile "/tmp/pwsh.1.gz" `
-ManDestination "/usr/share/man/man1/pwsh-preview.1.gz" `
-LinkInfo $linkInfo `
-Dependencies @("glibc") `
-AfterInstallScript $afterInstallScript `
-AfterRemoveScript $afterRemoveScript `
-Distribution "azl4" `
-HostArchitecture $HostArchitecture

$spec | Should -Match "(?m)^Release:\s+1\.azl4\r?$"
$spec | Should -Match "(?m)^\* .+ - 7\.6\.0_preview\.6-1\.azl4\r?$"
}

It "Should select the .NET 10 Azure Linux dependencies for <Distribution> with runtime <Runtime>" -TestCases @(
@{ Distribution = "cm"; Runtime = "linux-x64"; IncludeDotnetRuntime = $false }
@{ Distribution = "azl4"; Runtime = "linux-arm64"; IncludeDotnetRuntime = $false }
@{ Distribution = "cm"; Runtime = "fxdependent-linux-x64"; IncludeDotnetRuntime = $true }
@{ Distribution = "azl4"; Runtime = "fxdependent-linux-arm64"; IncludeDotnetRuntime = $true }
) {
param($Distribution, $Runtime, $IncludeDotnetRuntime)

$dependencies = & (Get-Module packaging) {
param($Distribution, $Runtime)

$previousOptions = $Script:Options
try {
$Script:Options = [pscustomobject] @{ Runtime = $Runtime }
@(Get-PackageDependencies -Distribution $Distribution)
}
finally {
$Script:Options = $previousOptions
}
} $Distribution $Runtime

$expectedDependencies = @(
"ca-certificates"
"glibc"
"icu"
"libgcc"
"libstdc++"
"openssl-libs"
"tzdata"
)
if ($IncludeDotnetRuntime) {
$expectedDependencies += "dotnet-runtime-10.0"
}

$dependencies | Should -BeExactly $expectedDependencies
}
}

Context "Azure Linux PMC mappings" {
BeforeAll {
$mappingPath = Join-Path $PSScriptRoot "../../tools/packages.microsoft.com/mapping.json"
$mapping = Get-Content -Path $mappingPath -Raw | ConvertFrom-Json
}

It "Should map <Channel> <Architecture> packages to <Url>" -TestCases @(
@{
Channel = "preview"
Architecture = "x86_64"
Url = "azurelinux-4-preview-microsoft-x86_64"
}
@{
Channel = "preview"
Architecture = "aarch64"
Url = "azurelinux-4-preview-microsoft-aarch64"
}
@{
Channel = "stable"
Architecture = "x86_64"
Url = "azurelinux-4-prod-microsoft-x86_64"
}
@{
Channel = "stable"
Architecture = "aarch64"
Url = "azurelinux-4-prod-microsoft-aarch64"
}
) {
param($Channel, $Architecture, $Url)

$mappedPackage = @($mapping.Packages | Where-Object url -EQ $Url)
$mappedPackage.Count | Should -Be 1
$mappedPackage[0].channel | Should -BeExactly $Channel
$mappedPackage[0].distribution | Should -BeExactly @("azl")
$mappedPackage[0].PackageFormat |
Should -BeExactly "PACKAGE_NAME-POWERSHELL_RELEASE-1.azl4.$Architecture.rpm"
}

It "Should remove the Azure Linux 4 beta mappings" {
@($mapping.Packages | Where-Object url -Like "azurelinux-4.0-beta-*").Count | Should -Be 0
}

It "Should retain all Azure Linux 3 .cm mappings" {
$azureLinux3Mappings = @($mapping.Packages | Where-Object url -Like "azurelinux-3.0-*")
$azureLinux3Mappings.Count | Should -Be 4
$azureLinux3Mappings.PackageFormat | Should -Match "\.cm\.(x86_64|aarch64)\.rpm$"
}
}

Context "Get-MacOSPackageIdentifierInfo function (New-MacOSPackage logic)" {
It "Should detect preview builds and return preview identifier" {
$result = Get-MacOSPackageIdentifierInfo -Version "7.6.0-preview.6" -LTS:$false
Expand Down
26 changes: 22 additions & 4 deletions tools/packages.microsoft.com/mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,36 @@
"channel": "preview"
},
{
"url": "azurelinux-4.0-beta-microsoft-aarch64",
"url": "azurelinux-4-preview-microsoft-x86_64",
"distribution": [
"azl"
],
"PackageFormat": "PACKAGE_NAME-POWERSHELL_RELEASE-1.cm.aarch64.rpm"
"PackageFormat": "PACKAGE_NAME-POWERSHELL_RELEASE-1.azl4.x86_64.rpm",
"channel": "preview"
},
{
"url": "azurelinux-4-preview-microsoft-aarch64",
"distribution": [
"azl"
],
"PackageFormat": "PACKAGE_NAME-POWERSHELL_RELEASE-1.azl4.aarch64.rpm",
"channel": "preview"
},
{
"url": "azurelinux-4.0-beta-microsoft-x86_64",
"url": "azurelinux-4-prod-microsoft-x86_64",
"distribution": [
"azl"
],
"PackageFormat": "PACKAGE_NAME-POWERSHELL_RELEASE-1.cm.x86_64.rpm"
"PackageFormat": "PACKAGE_NAME-POWERSHELL_RELEASE-1.azl4.x86_64.rpm",
"channel": "stable"
},
{
"url": "azurelinux-4-prod-microsoft-aarch64",
"distribution": [
"azl"
],
"PackageFormat": "PACKAGE_NAME-POWERSHELL_RELEASE-1.azl4.aarch64.rpm",
"channel": "stable"
},
{
"url": "microsoft-debian-stretch-prod",
Expand Down
47 changes: 40 additions & 7 deletions tools/packaging/packaging.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ $packagingStrings = Import-PowerShellDataFile "$PSScriptRoot\packaging.strings.p
Import-Module "$PSScriptRoot\..\Xml" -ErrorAction Stop -Force
$DebianDistributions = @("deb")
$RedhatFullDistributions = @("rh")
$RedhatFddDistributions = @("cm")
$RedhatFddDistributions = @("cm", "azl4")
$RedhatDistributions = @()
$RedhatDistributions += $RedhatFullDistributions
$RedhatDistributions += $RedhatFddDistributions
Expand Down Expand Up @@ -1265,10 +1265,15 @@ function New-UnixPackage {
throw "rpmbuild failed with exit code $exitCode"
}

# Find the generated RPM
$rpmFile = Get-ChildItem -Path (Join-Path $rpmsDir $HostArchitecture) -Filter "*.rpm" -ErrorAction Stop |
Sort-Object -Property LastWriteTime -Descending |
Select-Object -First 1
# Find the exact RPM produced from the spec metadata.
$rpmFileName = Get-RpmPackageFileName `
-Name $Name `
-Version $packageVersion `
-Iteration $Iteration `
-Distribution $DebDistro `
-HostArchitecture $HostArchitecture
$rpmArchitecturePath = Join-Path $rpmsDir $HostArchitecture
$rpmFile = Get-Item -Path (Join-Path $rpmArchitecturePath $rpmFileName) -ErrorAction Stop

if ($rpmFile) {
# Copy RPM to current location
Expand Down Expand Up @@ -1544,6 +1549,34 @@ Class LinkInfo
[string] $Destination
}

function Get-RpmPackageFileName
{
<#
.SYNOPSIS
Gets the RPM file name produced by rpmbuild for the supplied package metadata.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string] $Name,

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

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

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

[Parameter(Mandatory)]
[string] $HostArchitecture
)

$rpmVersion = $Version -replace '-', '_'
return "$Name-$rpmVersion-$Iteration.$Distribution.$HostArchitecture.rpm"
}

function New-RpmSpec
{
param(
Expand Down Expand Up @@ -1591,7 +1624,7 @@ function New-RpmSpec
# e.g., "7.6.0-preview.6" becomes Version: 7.6.0_preview.6
$rpmVersion = $Version -replace '-', '_'

# Build Release field with distribution suffix (e.g., "1.cm" or "1.rh")
# Build Release field with distribution suffix (e.g., "1.cm", "1.azl4", or "1.rh")
# Don't use RPM macros - build the full release string in PowerShell
$rpmRelease = "$Iteration.$Distribution"

Expand Down Expand Up @@ -2133,7 +2166,7 @@ function Get-PackageDependencies
"openssl-libs",
"libicu"
)
} elseif ($Distribution -eq 'cm') {
} elseif ($Distribution -in 'cm', 'azl4') {
# Azure Linux 3 and 4 use the same .NET 10 runtime dependencies:
# https://github.com/dotnet/dotnet-docker/blob/7962e8c9336303584720344bd644287a1fe77844/src/runtime-deps/10.0/azurelinux4.0/amd64/Dockerfile
$Dependencies = @(
Expand Down
Loading