Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0350978
Initial plan
Copilot Oct 17, 2025
545c522
Replace fpm with native rpmbuild for RPM package generation
Copilot Oct 17, 2025
a9b6632
Fix RPM spec file generation and cleanup
Copilot Oct 17, 2025
e8a1be0
Fix rpmbuild command execution and verify with comprehensive test
Copilot Oct 17, 2025
21511f9
Update linux packaging workflow to explicitly import packaging.psm1
Copilot Oct 18, 2025
3dbd356
Update Linux CI workflow to trigger packaging job for packaging changes
Copilot Oct 18, 2025
42ace23
Add back ci_build dependency to linux_packaging job
Copilot Oct 18, 2025
08cd012
Fix macOS and Linux packaging issues
Copilot Oct 18, 2025
0415c7f
Fix RPM package path duplication issue
Copilot Oct 18, 2025
fad01c2
Fix cross-architecture RPM builds with --target option
Copilot Oct 18, 2025
a1803b8
Fix cross-architecture RPM builds by omitting BuildArch for non-nativ…
Copilot Oct 18, 2025
9473c91
Fix package artifacts handling for GitHub Actions
Copilot Oct 18, 2025
6a78c10
Add Pester tests for Linux package name validation
Copilot Oct 18, 2025
16fb48b
Fix RPM package name validation regex
Copilot Oct 18, 2025
3c6d2e6
Simplify RPM version handling - just convert hyphens to underscores
Copilot Oct 18, 2025
563431c
Revert "Fix RPM package name validation regex"
Copilot Oct 18, 2025
4ef96b9
Add RPM spec file logging with GitHub Actions group support
Copilot Oct 18, 2025
fa902b5
Remove RPM macro and build release field with distribution suffix
Copilot Oct 19, 2025
404cde8
Add Azure Linux (Mariner) support for RPM builds
Copilot Oct 19, 2025
3c28c83
Merge branch 'master' into copilot/update-code-to-generate-rpm
TravisEz13 Oct 20, 2025
1419128
Disable binary stripping for cross-architecture RPM builds
Copilot Oct 20, 2025
5b0e023
Add detailed comments explaining cross-arch RPM build directives
Copilot Oct 20, 2025
6248d4b
Install fpm on Mariner for DEB package builds
Copilot Oct 20, 2025
a959d39
Apply suggestion from @TravisEz13
TravisEz13 Oct 20, 2025
2601b32
Apply suggestion from @TravisEz13
TravisEz13 Oct 20, 2025
5289ca4
Update tools/packaging/packaging.psm1
TravisEz13 Oct 20, 2025
3d79676
Update test/packaging/linux/package-validation.tests.ps1
TravisEz13 Oct 20, 2025
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
13 changes: 13 additions & 0 deletions .github/actions/test/linux-packaging/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ runs:
# Create the artifacts staging directory
New-Item -ItemType Directory -Path "$env:BUILD_ARTIFACTSTAGINGDIRECTORY" -Force | Out-Null

# Import packaging module to ensure RPM packaging changes are loaded
Import-Module ./build.psm1 -Force
Import-Module ./tools/packaging/packaging.psm1 -Force
Import-Module ./tools/ci.psm1
Restore-PSOptions -PSOptionsPath '${{ runner.workspace }}/build/psoptions.json'
$options = (Get-PSOptions)
Expand All @@ -75,6 +78,16 @@ runs:
Invoke-CIFinish
shell: pwsh

- name: Validate Package Names
run: |-
# Run Pester tests to validate package names
Import-Module Pester -Force
$testResults = Invoke-Pester -Path ./test/packaging/linux/package-validation.tests.ps1 -PassThru
if ($testResults.FailedCount -gt 0) {
throw "Package validation tests failed"
}
shell: pwsh

- name: Upload deb packages
uses: actions/upload-artifact@v4
with:
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/linux-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jobs:
# Set job outputs to values from filter step
outputs:
source: ${{ steps.filter.outputs.source }}
packagingChanged: ${{ steps.filter.outputs.packagingChanged }}
steps:
- name: checkout
uses: actions/checkout@v5
Expand Down Expand Up @@ -239,7 +240,7 @@ jobs:
needs:
- ci_build
- changes
if: ${{ needs.changes.outputs.source == 'true' }}
if: ${{ needs.changes.outputs.packagingChanged == 'true' }}
runs-on: ubuntu-latest
steps:
- name: checkout
Expand Down
21 changes: 17 additions & 4 deletions build.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -2401,11 +2401,24 @@ 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 -eq 'Both' -or $Scenario -eq 'Package') {
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"
# 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..."
if (!(Get-Command rpmbuild -ErrorAction SilentlyContinue)) {
Write-Warning "rpmbuild not found. Installing rpm-build package..."
Start-NativeExecution -sb ([ScriptBlock]::Create("$sudo $PackageManager install -y rpm-build")) -IgnoreExitcode
}
}
}
}

Expand Down
91 changes: 91 additions & 0 deletions test/packaging/linux/package-validation.tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

Describe "Linux Package Name Validation" {
BeforeAll {
# Determine artifacts directory (GitHub Actions or Azure DevOps)
$artifactsDir = if ($env:GITHUB_ACTIONS -eq 'true') {
"$env:GITHUB_WORKSPACE/../packages"
} else {
$env:SYSTEM_ARTIFACTSDIRECTORY
}

if (-not $artifactsDir) {
throw "Artifacts directory not found. GITHUB_WORKSPACE or SYSTEM_ARTIFACTSDIRECTORY must be set."
}

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

Context "RPM Package Names" {
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
}

$invalidPackages = @()
# Regex pattern for valid RPM package names.
# Breakdown:
# ^powershell\- : Starts with 'powershell-'
# (preview-|lts-)? : Optionally 'preview-' or 'lts-'
# \d+\.\d+\.\d+ : Version number (e.g., 7.6.0)
# (_[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.'
# (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) {
$invalidPackages += "$($package.Name) is not a valid RPM package name"
Write-Warning "$($package.Name) is not a valid RPM package name"
}
}

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

$rpmPackages.Count | Should -BeGreaterThan 0
}
}

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
}

$invalidPackages = @()
foreach ($package in $tarPackages) {
# Pattern matches: powershell-7.6.0-preview.6-linux-x64.tar.gz or powershell-7.6.0-linux-x64.tar.gz
# Also matches various runtime configurations
if ($package.Name -notmatch 'powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*.\d+\-)?(linux|osx|linux-musl)+\-(x64\-fxdependent|x64|arm32|arm64|x64\-musl-noopt\-fxdependent)\.(tar\.gz)') {
$invalidPackages += "$($package.Name) is not a valid tar.gz package name"
Write-Warning "$($package.Name) is not a valid tar.gz package name"
}
}

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

$tarPackages.Count | Should -BeGreaterThan 0
}
}

Context "Package Existence" {
It "Should find at least one package in artifacts directory" {
$allPackages = Get-ChildItem -Path $artifactsDir -Recurse -Include *.rpm, *.tar.gz, *.deb -ErrorAction SilentlyContinue

$allPackages.Count | Should -BeGreaterThan 0 -Because "At least one package should exist in the artifacts directory"
}
}
}
26 changes: 23 additions & 3 deletions tools/ci.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -874,16 +874,36 @@ function New-LinuxPackage
$packageObj = $package
}

Write-Log -message "Artifacts directory: ${env:BUILD_ARTIFACTSTAGINGDIRECTORY}"
Copy-Item $packageObj.FullName -Destination "${env:BUILD_ARTIFACTSTAGINGDIRECTORY}" -Force
# Determine artifacts directory (GitHub Actions or Azure DevOps)
$artifactsDir = if ($env:GITHUB_ACTIONS -eq 'true') {
"${env:GITHUB_WORKSPACE}/../packages"
} else {
"${env:BUILD_ARTIFACTSTAGINGDIRECTORY}"
}

# Ensure artifacts directory exists
if (-not (Test-Path $artifactsDir)) {
New-Item -ItemType Directory -Path $artifactsDir -Force | Out-Null
}

Write-Log -message "Artifacts directory: $artifactsDir"
Copy-Item $packageObj.FullName -Destination $artifactsDir -Force
}

if ($IsLinux)
{
# Determine artifacts directory (GitHub Actions or Azure DevOps)
$artifactsDir = if ($env:GITHUB_ACTIONS -eq 'true') {
"${env:GITHUB_WORKSPACE}/../packages"
} else {
"${env:BUILD_ARTIFACTSTAGINGDIRECTORY}"
}

# Create and package Raspbian .tgz
# Build must be clean for Raspbian
Start-PSBuild -PSModuleRestore -Clean -Runtime linux-arm -Configuration 'Release'
$armPackage = Start-PSPackage @packageParams -Type tar-arm -SkipReleaseChecks
Copy-Item $armPackage -Destination "${env:BUILD_ARTIFACTSTAGINGDIRECTORY}" -Force
Copy-Item $armPackage -Destination $artifactsDir -Force
}
}

Expand Down
Loading
Loading