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
223 changes: 217 additions & 6 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,16 @@ jobs:
throw "Could not resolve the Avalonia target framework from MSBuild"
}

dotnet publish src/UniGetUI.Avalonia/UniGetUI.Avalonia.csproj /noLogo /p:Configuration=Release /p:Platform=$Platform -p:RuntimeIdentifier=win-$Platform -v m
dotnet publish src/UniGetUI.Avalonia/UniGetUI.Avalonia.csproj `
/noLogo `
/p:Configuration=Release `
/p:Platform=$Platform `
/p:RuntimeIdentifier=win-$Platform `
/p:PublishProfile=Win-$Platform-NativeAot `
/p:UseSharedCompilation=false `
/p:BuildInParallel=false `
/m:1 `
-v m
if ($LASTEXITCODE -ne 0) { throw "dotnet publish Avalonia failed" }

# Stage binaries
Expand Down Expand Up @@ -286,6 +295,26 @@ jobs:

# Installer is created in output during the previous step

- name: Capture artifact sizes
shell: pwsh
run: |
$Platform = '${{ matrix.platform }}'
$SizesFile = "output/sizes.$Platform.json"
$UncompressedSize = (Get-ChildItem "unigetui_bin" -Recurse -File | Measure-Object -Property Length -Sum).Sum
$Artifacts = Get-ChildItem "output" -File | Where-Object { $_.Name -ne "sizes.$Platform.json" } | ForEach-Object {
@{ Name = $_.Name; SizeBytes = $_.Length }
}
$Report = @{
Platform = $Platform
RuntimeIdentifier = "win-$Platform"
UncompressedSizeBytes = $UncompressedSize
Artifacts = $Artifacts
Timestamp = [DateTimeOffset]::UtcNow.ToString("o")
}
$Report | ConvertTo-Json -Depth 4 | Set-Content $SizesFile -Encoding UTF8
Write-Host "Artifact sizes saved to $SizesFile"
Get-Content $SizesFile

- name: Code-sign installer
if: ${{ fromJSON(needs.preflight.outputs.dry-run) == false }}
shell: pwsh
Expand Down Expand Up @@ -333,15 +362,19 @@ jobs:
- os: macos-latest
name: macos-arm64
runtime: osx-arm64
publish_profile: osx-arm64-NativeAot
- os: macos-latest
name: macos-x64
runtime: osx-x64
publish_profile: osx-x64-NativeAot
- os: ubuntu-latest
name: linux-x64
runtime: linux-x64
publish_profile: linux-x64-NativeAot
- os: ubuntu-latest
name: linux-arm64
runtime: linux-arm64
publish_profile: linux-arm64-NativeAot

steps:
- name: Checkout
Expand All @@ -360,6 +393,53 @@ jobs:
restore-keys: |
${{ runner.os }}-nuget-

- name: Install Linux arm64 NativeAOT toolchain
if: matrix.runtime == 'linux-arm64'
shell: bash
run: |
set -euo pipefail

. /etc/os-release
sudo dpkg --add-architecture arm64

# Keep the runner's default Ubuntu feeds bound to amd64, then add the
# Ubuntu Ports arm64 feed that provides the target CRT and zlib objects.
if compgen -G "/etc/apt/sources.list.d/*.sources" > /dev/null; then
for source in /etc/apt/sources.list.d/*.sources; do
if ! grep -q '^Architectures:' "$source"; then
sudo sed -i '/^Types: deb$/a Architectures: amd64' "$source"
fi
done
fi

if [ -f /etc/apt/sources.list ]; then
sudo sed -i -E '/^deb /s/^deb /deb [arch=amd64] /' /etc/apt/sources.list
fi

sudo tee /etc/apt/sources.list.d/ubuntu-arm64.sources >/dev/null <<EOF
Types: deb
URIs: http://ports.ubuntu.com/ubuntu-ports/
Suites: ${VERSION_CODENAME} ${VERSION_CODENAME}-updates ${VERSION_CODENAME}-backports
Components: main restricted universe multiverse
Architectures: arm64
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://ports.ubuntu.com/ubuntu-ports/
Suites: ${VERSION_CODENAME}-security
Components: main restricted universe multiverse
Architectures: arm64
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
EOF

sudo apt-get update
sudo apt-get install -y --no-install-recommends \
clang \
llvm \
binutils-aarch64-linux-gnu \
gcc-aarch64-linux-gnu \
zlib1g-dev:arm64

- name: Set version
shell: pwsh
run: |
Expand All @@ -372,12 +452,37 @@ jobs:

- name: Publish
working-directory: src
shell: pwsh
run: |
$PublishProfile = '${{ matrix.publish_profile }}'
$PublishArgs = @(
'publish',
'UniGetUI.Avalonia/UniGetUI.Avalonia.csproj',
'--configuration', 'Release',
'--runtime', '${{ matrix.runtime }}',
'--self-contained', 'true',
'--output', '../bin/${{ matrix.name }}'
)
if ($PublishProfile) {
$PublishArgs += "/p:PublishProfile=$PublishProfile"
}
dotnet @PublishArgs

- name: Remove oversized Linux debug symbols
if: runner.os == 'Linux'
shell: pwsh
run: |
dotnet publish UniGetUI.Avalonia/UniGetUI.Avalonia.csproj \
--configuration Release \
--runtime ${{ matrix.runtime }} \
--self-contained true \
--output ../bin/${{ matrix.name }}
$PublishDir = "bin/${{ matrix.name }}"
$MaxDebugSymbolSizeBytes = 1MB
$DebugSymbolsToRemove = @(Get-ChildItem $PublishDir -Include "*.dbg", "*.pdb" -File -Recurse | Where-Object {
$_.Length -gt $MaxDebugSymbolSizeBytes
})

if ($DebugSymbolsToRemove.Count -gt 0) {
$RemovedDebugSymbolBytes = ($DebugSymbolsToRemove | Measure-Object -Property Length -Sum).Sum
$DebugSymbolsToRemove | Remove-Item -Force
Write-Host ("Removed {0} oversized Linux debug symbols above {1:N2} MiB ({2:N2} MiB total)." -f $DebugSymbolsToRemove.Count, ($MaxDebugSymbolSizeBytes / 1MB), ($RemovedDebugSymbolBytes / 1MB))
}

- name: Install macOS packaging tools
if: runner.os == 'macOS'
Expand Down Expand Up @@ -534,6 +639,28 @@ jobs:
-Iteration $RpmIteration `
-Architecture $RpmArch

- name: Capture artifact sizes
shell: pwsh
run: |
$Name = '${{ matrix.name }}'
$Runtime = '${{ matrix.runtime }}'
$SizesFile = "output/sizes.$Name.json"
$SourceDir = if ('${{ runner.os }}' -eq 'macOS') { "UniGetUI.app/Contents/MacOS" } else { "bin/$Name" }
$UncompressedSize = (Get-ChildItem $SourceDir -Recurse -File -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum
$Artifacts = Get-ChildItem "output" -File -ErrorAction SilentlyContinue | Where-Object { $_.Name -ne "sizes.$Name.json" } | ForEach-Object {
@{ Name = $_.Name; SizeBytes = $_.Length }
}
$Report = @{
Platform = $Name
RuntimeIdentifier = $Runtime
UncompressedSizeBytes = $UncompressedSize
Artifacts = $Artifacts
Timestamp = [DateTimeOffset]::UtcNow.ToString("o")
}
$Report | ConvertTo-Json -Depth 4 | Set-Content $SizesFile -Encoding UTF8
Write-Host "Artifact sizes saved to $SizesFile"
Get-Content $SizesFile

- name: Upload artifacts
uses: actions/upload-artifact@v7
with:
Expand Down Expand Up @@ -588,6 +715,39 @@ jobs:
Get-Content $ChecksumFile
echo "::endgroup::"

- name: Generate consolidated size report
shell: pwsh
working-directory: output
run: |
$SizeFiles = Get-ChildItem -Path . -Recurse -File -Filter "sizes.*.json" | Sort-Object Name
if (-not $SizeFiles) {
Write-Host "No size files found."
return
}

$Rows = foreach ($file in $SizeFiles) {
$data = Get-Content $file.FullName -Raw | ConvertFrom-Json
$uncompressedMiB = [math]::Round($data.UncompressedSizeBytes / 1MB, 2)
foreach ($artifact in $data.Artifacts) {
[PSCustomObject]@{
Platform = $data.Platform
RID = $data.RuntimeIdentifier
Artifact = $artifact.Name
CompressedMiB = [math]::Round($artifact.SizeBytes / 1MB, 2)
UncompressedMiB = $uncompressedMiB
}
}
}

$SizeReportFile = Join-Path $PWD "sizes.md"
$Lines = @("# UniGetUI Release Artifact Sizes", "")
$Lines += $Rows | Format-Table -AutoSize | Out-String -Stream | Where-Object { $_.Trim() -ne '' }
Set-Content -Path $SizeReportFile -Value $Lines -Encoding utf8NoBOM

echo "::group::sizes"
Get-Content $SizeReportFile
echo "::endgroup::"

- name: Create GitHub Release
shell: pwsh
env:
Expand Down Expand Up @@ -683,3 +843,54 @@ jobs:
remote: releases
source_path: Devolutions.UniGetUI.*
working_directory: onedrive-staging

size-report:
name: Consolidated Size Report
runs-on: ubuntu-latest
needs: [preflight, build, build-avalonia]
if: always() && needs.build.result != 'cancelled' && needs.build-avalonia.result != 'cancelled'

steps:
- name: Download artifacts
uses: actions/download-artifact@v8
with:
path: output

- name: Generate consolidated size report
shell: pwsh
working-directory: output
run: |
$SizeFiles = Get-ChildItem -Path . -Recurse -File -Filter "sizes.*.json" | Sort-Object Name
if (-not $SizeFiles) {
Write-Host "No size files found."
return
}

$Rows = foreach ($file in $SizeFiles) {
$data = Get-Content $file.FullName -Raw | ConvertFrom-Json
$uncompressedMiB = [math]::Round($data.UncompressedSizeBytes / 1MB, 2)
foreach ($artifact in $data.Artifacts) {
[PSCustomObject]@{
Platform = $data.Platform
RID = $data.RuntimeIdentifier
Artifact = $artifact.Name
CompressedMiB = [math]::Round($artifact.SizeBytes / 1MB, 2)
UncompressedMiB = $uncompressedMiB
}
}
}

$SizeReportFile = Join-Path $PWD "sizes.md"
$Lines = @("# UniGetUI Release Artifact Sizes", "")
$Lines += $Rows | Format-Table -AutoSize | Out-String -Stream | Where-Object { $_.Trim() -ne '' }
Set-Content -Path $SizeReportFile -Value $Lines -Encoding utf8NoBOM

echo "::group::sizes"
Get-Content $SizeReportFile
echo "::endgroup::"

- name: Upload size report
uses: actions/upload-artifact@v7
with:
name: UniGetUI-size-report
path: output/sizes.md
88 changes: 73 additions & 15 deletions .github/workflows/cli-headless-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,26 @@ jobs:
daemon_project: UniGetUI.Avalonia/UniGetUI.Avalonia.csproj
daemon_build_args: '-p:Platform=x64'
manifest: testing/automation/cli-e2e.manifest.windows.json
- name: Windows (NativeAOT)
os: windows-latest
solution: UniGetUI.Windows.slnx
daemon_project: UniGetUI.Avalonia/UniGetUI.Avalonia.csproj
daemon_publish_profile: Win-x64-NativeAot
daemon_build_args: '-p:Platform=x64'
manifest: testing/automation/cli-e2e.manifest.windows.json
- name: Linux (Avalonia)
os: ubuntu-latest
solution: UniGetUI.Avalonia.slnx
daemon_project: UniGetUI.Avalonia/UniGetUI.Avalonia.csproj
daemon_build_args: ''
manifest: testing/automation/cli-e2e.manifest.linux.json
- name: Linux (NativeAOT)
os: ubuntu-latest
solution: UniGetUI.Avalonia.slnx
daemon_project: UniGetUI.Avalonia/UniGetUI.Avalonia.csproj
daemon_publish_profile: linux-x64-NativeAot
daemon_build_args: ''
manifest: testing/automation/cli-e2e.manifest.linux-nativeaot.json

name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -76,22 +90,66 @@ jobs:
working-directory: src
shell: pwsh
run: |
$args = @(
'build',
'${{ matrix.daemon_project }}',
'--no-restore',
'--configuration',
'${{ env.CONFIGURATION }}',
'--verbosity',
'minimal',
'/p:UseSharedCompilation=false',
'/m:1'
)
if ('${{ matrix.daemon_build_args }}') {
$args += '${{ matrix.daemon_build_args }}'
}
$PublishProfile = '${{ matrix.daemon_publish_profile }}'
$BuildArgs = '${{ matrix.daemon_build_args }}'

dotnet build-server shutdown
dotnet @args

if ($PublishProfile) {
$RuntimeIdentifier = $PublishProfile -replace '-NativeAot$', '' -replace '^Win-', 'win-' -replace '^linux-', 'linux-' -replace '^osx-', 'osx-'
$OutputPath = Join-Path (Resolve-Path '..') "artifacts/e2e-nativeaot/$RuntimeIdentifier"
New-Item -ItemType Directory -Force -Path $OutputPath | Out-Null

$args = @(
'publish',
'${{ matrix.daemon_project }}',
'--no-restore',
'--configuration',
'${{ env.CONFIGURATION }}',
'--runtime',
$RuntimeIdentifier,
'--self-contained',
'true',
'--output',
$OutputPath,
'--verbosity',
'minimal',
'/p:UseSharedCompilation=false',
'/m:1',
"/p:PublishProfile=$PublishProfile"
)
if ($BuildArgs) {
$args += $BuildArgs
}
dotnet @args

$exeName = if ('${{ runner.os }}' -eq 'Windows') { 'UniGetUI.exe' } else { 'UniGetUI' }
$daemonExe = Join-Path $OutputPath $exeName
if (-not (Test-Path $daemonExe)) {
throw "NativeAOT daemon executable was not produced at $daemonExe"
}
if ('${{ runner.os }}' -ne 'Windows') {
chmod +x $daemonExe
}
echo "UNIGETUI_DAEMON_EXE=$daemonExe" >> $Env:GITHUB_ENV
}
else {
$args = @(
'build',
'${{ matrix.daemon_project }}',
'--no-restore',
'--configuration',
'${{ env.CONFIGURATION }}',
'--verbosity',
'minimal',
'/p:UseSharedCompilation=false',
'/m:1'
)
if ($BuildArgs) {
$args += $BuildArgs
}
dotnet @args
}

- name: Upgrade pip tooling
shell: pwsh
Expand Down
Loading
Loading