Publish PyKotor Tools CI/CD #170
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Publish PyKotor Tools CI/CD | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
env: | |
OS_RUNNERS_JSON: '["windows-2019", "ubuntu-20.04", "macos-12"]' | |
PYTHON_VERSIONS_JSON: '["3.8", "3.9", "3.10", "3.11", "3.12"]' | |
ARCHITECTURES_JSON: '["x86", "x64"]' | |
INTERPRETERS_JSON: '["python"]' | |
UPX_VERSION: '4.2.2' | |
USE_UPX: true | |
BUILD_BOOTLOADERS: false # TODO(th3w1zard1): | |
on: | |
# push: | |
workflow_dispatch: | |
schedule: | |
- cron: '0 6 * * 1' # Runs every Monday at 06:00 UTC | |
permissions: | |
contents: write | |
jobs: | |
setup: | |
runs-on: ubuntu-latest | |
outputs: | |
os: ${{ steps.set_env.outputs.os }} | |
python-version: ${{ steps.set_env.outputs.python-version }} | |
architecture: ${{ steps.set_env.outputs.architecture }} | |
python-pypy: ${{ steps.set_env.outputs.python-pypy }} | |
#qt_version: ${#{ steps.set_env.outputs.qt_version }} | |
steps: | |
- name: Set environment variables | |
id: set_env | |
run: | | |
$singleLineJson = '${{ env.OS_RUNNERS_JSON }}' -replace "`r", "" -replace "`n", "" | |
echo "os<<EOF" >> $env:GITHUB_OUTPUT | |
echo $singleLineJson >> $env:GITHUB_OUTPUT | |
echo "EOF" >> $env:GITHUB_OUTPUT | |
$singleLineJson = '${{ env.PYTHON_VERSIONS_JSON }}' -replace "`r", "" -replace "`n", "" | |
echo "python-version<<EOF" >> $env:GITHUB_OUTPUT | |
echo $singleLineJson >> $env:GITHUB_OUTPUT | |
echo "EOF" >> $env:GITHUB_OUTPUT | |
$singleLineJson = '${{ env.ARCHITECTURES_JSON }}' -replace "`r", "" -replace "`n", "" | |
echo "architecture<<EOF" >> $env:GITHUB_OUTPUT | |
echo $singleLineJson >> $env:GITHUB_OUTPUT | |
echo "EOF" >> $env:GITHUB_OUTPUT | |
$singleLineJson = '${{ env.INTERPRETERS_JSON }}' -replace "`r", "" -replace "`n", "" | |
echo "python-pypy<<EOF" >> $env:GITHUB_OUTPUT | |
echo $singleLineJson >> $env:GITHUB_OUTPUT | |
echo "EOF" >> $env:GITHUB_OUTPUT | |
shell: pwsh | |
build: | |
needs: setup | |
runs-on: ${{ matrix.os }} | |
strategy: | |
fail-fast: false # Disable automatic cancellation of other jobs | |
matrix: | |
os: ${{ fromJson(needs.setup.outputs.os) }} | |
python-version: ${{ fromJson(needs.setup.outputs.python-version) }} | |
architecture: ${{ fromJson(needs.setup.outputs.architecture) }} | |
python_pypy: ${{ fromJson(needs.setup.outputs.python-pypy) }} | |
qt_version: ['pyqt5'] | |
include: | |
- arch: x86 | |
vc_redist2015: "https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe" | |
vc_redist-latest: "https://aka.ms/vs/17/release/vc_redist.x86.exe" | |
vc_redist2019: "https://aka.ms/vs/17/release/vc_redist.x86.exe" | |
- arch: x64 | |
vc_redist2015: "https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe" | |
vc_redist-latest: "https://aka.ms/vs/17/release/vc_redist.x64.exe" | |
vc_redist2019: "https://aka.ms/vs/17/release/vc_redist.x64.exe" | |
exclude: | |
# unix x86 is definitely not supported. | |
- os: ubuntu-20.04 | |
architecture: x86 | |
- os: macos-12 | |
architecture: x86 | |
# latest PyPy version as of 17/03/2024 is 3.10. | |
- python_pypy: 'pypy' | |
python-version: '3.11' | |
- python_pypy: 'pypy' | |
python-version: '3.12' | |
# PyQt5 doesn't seem to be compatible with PyPy | |
- python_pypy: "pypy" | |
qt_version: 'pyqt5' | |
- python_pypy: "pypy" | |
qt_version: 'pyside2' | |
- python_pypy: "pypy" | |
qt_version: 'pyqt6' | |
- python_pypy: "pypy" | |
python-version: '3.10' | |
os: 'windows-2019' | |
steps: | |
- name: Determine Python version string | |
id: set-python-version | |
run: | | |
if ( "${{ matrix.python_pypy }}" -eq "pypy" ) { | |
Add-Content -Path $env:GITHUB_ENV -Value "PYTHON_VERSION=pypy-${{ matrix.python-version }}" | |
} else { | |
Add-Content -Path $env:GITHUB_ENV -Value "PYTHON_VERSION=${{ matrix.python-version }}" | |
} | |
shell: pwsh | |
env: | |
MATRIX_ARCH: ${{ matrix.architecture }} | |
- uses: actions/checkout@v4 | |
- name: Test Powershell installer | |
if: ${{ runner.os != 'Windows' }} | |
id: setup-powershell | |
run: | | |
bash ./install_powershell.sh | |
shell: bash | |
- name: Set up pypy ${{ matrix.python-version }} | |
if: ${{ matrix.python_pypy == 'pypy' }} | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ env.PYTHON_VERSION }} | |
architecture: ${{ matrix.architecture }} | |
- name: Reset APT sources to default | |
if: ${{ runner.os == 'Linux' }} | |
run: | | |
echo "Resetting APT sources to default Ubuntu repositories" | |
sudo rm /etc/apt/sources.list | |
echo "deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs) main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list | |
echo "deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs)-updates main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list | |
echo "deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs)-backports main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list | |
echo "deb http://security.ubuntu.com/ubuntu $(lsb_release -cs)-security main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list | |
sudo apt-get update -y | |
shell: bash | |
- name: Set UPX download URL | |
# upx docs express that crashes are happening on ventura and above with upx, don't use on mac. | |
if: runner.os != 'macOS' | |
id: upx_setup | |
run: | | |
$build = "no" | |
$archiveName = "" | |
if ("${{ runner.os }}" -eq "Windows") { | |
if ("${{ matrix.architecture }}" -eq "x86") { | |
$archiveName = "upx-${{ env.UPX_VERSION }}-win32.zip" | |
} else { | |
$archiveName = "upx-${{ env.UPX_VERSION }}-win64.zip" | |
} | |
} elseif ("${{ runner.os }}" -eq "Linux") { | |
$archiveName = "upx-${{ env.UPX_VERSION }}-amd64_linux.tar.xz" | |
} elseif ("${{ runner.os }}" -eq "macOS") { | |
$build = "yes" | |
$archiveName = "upx-${{ env.UPX_VERSION }}-src.tar.xz" | |
} | |
$url = "https://github.com/upx/upx/releases/download/v${{ env.UPX_VERSION }}/$archiveName" | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "build=$build" | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "url=$url" | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "archiveName=$archiveName" | |
shell: pwsh | |
- name: Download and prepare UPX | |
if: runner.os != 'macOS' | |
run: | | |
$ext = "${{ runner.os }}" -eq "Windows" ? "zip" : "tar.xz" | |
$url = "${{ steps.upx_setup.outputs.url }}" | |
$archiveName = "${{ steps.upx_setup.outputs.archiveName }}" | |
$outputPath = "upx-dir" | |
# Use Invoke-WebRequest or curl depending on the OS | |
if ("${{ runner.os }}" -eq "Windows") { | |
Invoke-WebRequest -Uri $url -OutFile $archiveName | |
} elseif ("${{ runner.os }}" -eq "Linux") { | |
curl -L $url -o $archiveName | |
} | |
New-Item -ItemType Directory -Force -Path "upx-dir" -ErrorAction SilentlyContinue | |
if ("${{ runner.os }}" -ne "macOS") { | |
if ($ext -eq "zip") { | |
$fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($archiveName) | |
Expand-Archive -Path $archiveName -DestinationPath "temp_folder_upx" | |
if (-not (Test-Path -Path "upx-dir")) { | |
New-Item -ItemType Directory -Path "upx-dir" | |
} | |
Get-ChildItem -LiteralPath "temp_folder_upx/$fileNameWithoutExtension" -Recurse | Move-Item -Destination "upx-dir" | |
Remove-Item "temp_folder_upx" -Recurse -Force -ErrorAction SilentlyContinue | |
} else { | |
tar -xvf $archiveName --strip-components=1 -C "upx-dir" | |
} | |
Remove-Item $archiveName # Clean up downloaded archive | |
} | |
shell: pwsh | |
- name: Set UPX directory path | |
if: runner.os != 'macOS' | |
id: upx_dir | |
run: | | |
$upx_dir = "./upx-dir" | |
$upx_dir = $([System.IO.Path]::GetFullPath('./upx-dir')) | |
Dir -Recurse $upx_dir | Get-Childitem | |
echo "UPX_DIR=$upx_dir" | Out-File -FilePath $env:GITHUB_ENV -Append | |
Write-Output "UPX_DIR set to '$upx_dir'" | |
shell: pwsh | |
- name: Install Visual Studio 2015 C++ Redistributable | |
if: runner.os == 'Windows' | |
run: | | |
$url = "${{ matrix.vc_redist2015 }}" | |
$output = "vc_redist.exe" | |
Invoke-WebRequest -Uri $url -OutFile $output | |
Start-Process $output -ArgumentList '/install', '/quiet', '/norestart' -Wait | |
Remove-Item -Path $output | |
#choco install vcredist2015 -y | |
shell: pwsh | |
- name: Install Visual Studio 2019 C++ Redistributable | |
if: runner.os == 'Windows' | |
run: | | |
$url = "${{ matrix.vc_redist2019 }}" | |
$output = "vc_redist.exe" | |
Invoke-WebRequest -Uri $url -OutFile $output | |
Start-Process $output -ArgumentList '/install', '/quiet', '/norestart' -Wait | |
Remove-Item -Path $output | |
#choco install vcredist2019 -y | |
shell: pwsh | |
- name: Install Visual Studio latest C++ Redistributable | |
if: runner.os == 'Windows' | |
run: | | |
$url = "${{ matrix.vc_redist-latest }}" | |
$output = "vc_redist.exe" | |
Invoke-WebRequest -Uri $url -OutFile $output | |
Start-Process $output -ArgumentList '/install', '/quiet', '/norestart' -Wait | |
Remove-Item -Path $output | |
shell: pwsh | |
- name: Install Holocron Toolset dependencies | |
if: ${{ success() || failure() }} | |
env: | |
MATRIX_ARCH: ${{ matrix.architecture }} | |
id: toolset_deps | |
run: | # known pyinstaller versions that work with upx compressions, not all are available on all python versions. | |
try { | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_toolset_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} -force_python_version ${{ matrix.python-version }} | |
Write-Host "Python executable path: $pythonExePath" | |
& $pythonExePath -m pip install --upgrade pip | |
if ("${{ runner.os }}" -eq "Windows") { | |
if ("${{ matrix.python-version }}" -eq "3.12") { | |
pip install pyinstaller --prefer-binary -U | |
} elseif ("${{ matrix.python-version }}" -eq "3.11") { | |
pip install "pyinstaller==5.13.2" --prefer-binary | |
} else { | |
pip install "pyinstaller==5.4" --prefer-binary | |
} | |
} else { | |
pip install pyinstaller -U --prefer-binary | |
} | |
$env:QT_API = if (-not [string]::IsNullOrEmpty($env:QT_API)) { $env:QT_API } else { "${{ matrix.qt_version }}" } | |
$output = "" | |
$errorLines = @() | |
. ./compile/deps_toolset.ps1 -noprompt -venv_name .venv_toolset_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} 2>&1 | ForEach-Object { | |
Write-Output $_.ToString() | |
$output += $_.ToString() + "`n" | |
if($_ -match 'ERROR:') { | |
$errorLines += $_.ToString() | |
} | |
} | |
if ($errorLines.Count -gt 0) { | |
$errorLines | ForEach-Object { Write-Error $_ } | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} else { | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=true" | |
} | |
} catch { | |
Write-Host -ForegroundColor Red "Detailed Error Report:" | |
Write-Host -ForegroundColor Red "Message: $($_.Exception.Message)" | |
# Attempt to provide a more detailed location of the error | |
if ($_.InvocationInfo -and $_.InvocationInfo.MyCommand) { | |
Write-Host -ForegroundColor Red "Command Name: $($_.InvocationInfo.MyCommand.Name)" | |
Write-Host -ForegroundColor Red "Script Name: $($_.InvocationInfo.ScriptName)" | |
Write-Host -ForegroundColor Red "Line Number: $($_.InvocationInfo.ScriptLineNumber)" | |
Write-Host -ForegroundColor Red "Line: $($_.InvocationInfo.Line)" | |
} else { | |
Write-Host -ForegroundColor Red "No invocation information available." | |
} | |
# Extract and display the script stack trace if available | |
if ($_.ScriptStackTrace) { | |
Write-Host -ForegroundColor Red "Script Stack Trace:" | |
Write-Host -ForegroundColor Red $_.ScriptStackTrace | |
} else { | |
Write-Host -ForegroundColor Red "No script stack trace available." | |
} | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} | |
shell: pwsh | |
- name: HolocronToolset - Adjust RPATH for shared libraries in the virtual environment | |
if: ${{ (success() || failure()) && runner.os == 'Disabled_Linux' && steps.toolset_deps.outputs.success == 'true' }} | |
run: | | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_toolset_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
# Ensure patchelf is installed | |
sudo apt-get update && sudo apt-get install -y patchelf | |
# Find the virtual environment's site-packages directory | |
$venvPath = $env:VIRTUAL_ENV | |
Write-Host "Virtual environment path: $venvPath" | |
# Dynamically find the Python version directory inside the venv | |
$pythonLibPath = Get-ChildItem -LiteralPath "$venvPath/lib" | Where-Object { $_.PSIsContainer } | Select-Object -First 1 | |
$sitePackagesPath = Join-Path -Path $pythonLibPath.FullName -ChildPath "site-packages" | |
Write-Host "Site-packages path: $sitePackagesPath" | |
# Use patchelf to adjust RPATH for all shared libraries in the virtual environment | |
Get-ChildItem -LiteralPath $sitePackagesPath -Filter *.so -Recurse | ForEach-Object { | |
$libPath = $_.FullName | |
Write-Host "Patching $libPath" | |
sudo patchelf --set-rpath '$ORIGIN' $libPath | |
} | |
shell: pwsh | |
- name: Search for DLL files | |
if: ${{ matrix.python-version == '3.12_Disabled' && runner.os == 'Windows' }} | |
run: | | |
Get-PSDrive -PSProvider FileSystem | ForEach-Object { | |
$drive = $_.Root | |
Write-Host "Searching in $drive" | |
Get-ChildItem -LiteralPath $drive -Filter 'api-ms-win-crt-*.dll' -Recurse -ErrorAction SilentlyContinue -Force | ForEach-Object { | |
Write-Host $_.FullName | |
} | |
} | |
shell: pwsh | |
- name: Search for DLL files | |
if: ${{ matrix.python-version == '3.12' && runner.os == 'Windows' }} | |
run: | | |
$nullDir = New-Item -Path "NullDir" -ItemType Directory -Force | |
Get-PSDrive -PSProvider FileSystem | ForEach-Object { | |
$drive = $_.Root | |
Write-Host "Searching in $drive" | |
robocopy $drive $nullDir 'api-ms-win-core-path-l1-1-0.dll' /s /ndl /njh /njs /nc /ns /np | Where-Object { $_ -notlike '*Bytes*' } | ForEach-Object { | |
$path = Join-Path -Path $drive -ChildPath $_.Trim() | |
if(Test-Path $path) { | |
Write-Host $path | |
} | |
} | |
} | |
Remove-Item -Path "NullDir" -Force | |
shell: pwsh | |
- name: Compile Holocron Toolset | |
if: ${{ (success() || failure()) && steps.toolset_deps.outputs.success == 'true' }} | |
run: | | |
$upxDir = $env:UPX_DIR | |
Write-Host "Using UPX directory at '$upxDir'" | |
$output = "" | |
$env:PYTHONOPTIMIZE = "1" | |
. ./compile/compile_toolset.ps1 -noprompt -venv_name .venv_toolset_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} -upx_dir $upxDir 2>&1 | ForEach-Object { | |
Write-Output $_.ToString() | |
$output += $_.ToString() + "`n" | |
if($_ -match 'ERROR:') { | |
$errorLines += $_.ToString() | |
} | |
} | |
$warningCount = 0 | |
$output -split "`n" | ForEach-Object { | |
if ($_ -match 'WARNING: Library not found: could not resolve' -or | |
$_ -match 'WARNING: Cannot find ' -or | |
$_ -match 'WARNING: lib not found:' -or | |
$_ -match 'WARNING: Tcl modules directory' -or | |
$_ -match 'WARNING: Failed to upx strip') { | |
$warningCount++ | |
} | |
} | |
if ($errorLines.Count -gt 0) { | |
$errorLines | ForEach-Object { Write-Error $_ } | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} elseif ($warningCount -ge 3) { | |
Write-Output "Many warnings raised, pyinstaller was probably unsuccessful." | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} else { | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=true" | |
} | |
shell: pwsh | |
- name: HolocronToolset - Create Static Binary | |
if: ${{ (success() || failure()) && runner.os == 'Disabled_Linux' && steps.toolset_deps.outputs.success == 'true' }} | |
run: | | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_toolset_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
& $pythonExePath -m pip install staticx | |
staticx ./dist/HolocronToolset ./dist/HolocronToolset-static | |
# Rename the static binary for clarity and consistency | |
Write-Output "./dist/HolocronToolset-static --> ./dist/HolocronToolset" | |
Move-Item -LiteralPath ./dist/HolocronToolset-static -Destination ./dist/HolocronToolset -Force | |
shell: pwsh | |
- name: Install HoloPatcher dependencies | |
if: ${{ success() || failure() }} | |
env: | |
MATRIX_ARCH: ${{ matrix.architecture }} | |
id: holopatcher_deps | |
run: | # known pyinstaller versions that work with upx compressions, not all are available on all python versions. | |
try { | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_holopatcher_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} -force_python_version ${{ matrix.python-version }} | |
& $pythonExePath -m pip install --upgrade pip | |
if ("${{ runner.os }}" -eq "Windows") { | |
if ("${{ matrix.python-version }}" -eq "3.12") { | |
pip install "pyinstaller==5.13.2" --prefer-binary | |
} elseif ("${{ matrix.python-version }}" -eq "3.11") { | |
pip install "pyinstaller==5.13.2" --prefer-binary | |
} else { | |
pip install "pyinstaller==5.4" --prefer-binary | |
} | |
} else { | |
pip install pyinstaller -U --prefer-binary | |
} | |
$output = "" | |
$errorLines = @() | |
. ./compile/deps_holopatcher.ps1 -noprompt -venv_name .venv_holopatcher_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} 2>&1 | ForEach-Object { | |
Write-Output $_.ToString() | |
$output += $_.ToString() + "`n" | |
if($_ -match 'ERROR:') { | |
$errorLines += $_.ToString() | |
} | |
} | |
if ($errorLines.Count -gt 0) { | |
$errorLines | ForEach-Object { Write-Error $_ } | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} else { | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=true" | |
} | |
} catch { | |
Write-Host -ForegroundColor Red "Detailed Error Report:" | |
Write-Host -ForegroundColor Red "Message: $($_.Exception.Message)" | |
# Attempt to provide a more detailed location of the error | |
if ($_.InvocationInfo -and $_.InvocationInfo.MyCommand) { | |
Write-Host -ForegroundColor Red "Command Name: $($_.InvocationInfo.MyCommand.Name)" | |
Write-Host -ForegroundColor Red "Script Name: $($_.InvocationInfo.ScriptName)" | |
Write-Host -ForegroundColor Red "Line Number: $($_.InvocationInfo.ScriptLineNumber)" | |
Write-Host -ForegroundColor Red "Line: $($_.InvocationInfo.Line)" | |
} else { | |
Write-Host -ForegroundColor Red "No invocation information available." | |
} | |
# Extract and display the script stack trace if available | |
if ($_.ScriptStackTrace) { | |
Write-Host -ForegroundColor Red "Script Stack Trace:" | |
Write-Host -ForegroundColor Red $_.ScriptStackTrace | |
} else { | |
Write-Host -ForegroundColor Red "No script stack trace available." | |
} | |
# Log the error to GitHub Actions output or another logging mechanism | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} | |
shell: pwsh | |
- name: HoloPatcher - Adjust RPATH for shared libraries in the virtual environment | |
if: ${{ (success() || failure()) && runner.os == 'Disabled_Linux' && steps.holopatcher_deps.outputs.success == 'true' }} | |
run: | | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_holopatcher_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
# Ensure patchelf is installed | |
sudo apt-get update && sudo apt-get install -y patchelf | |
# Find the virtual environment's site-packages directory | |
$venvPath = $env:VIRTUAL_ENV | |
Write-Host "Virtual environment path: $venvPath" | |
# Dynamically find the Python version directory inside the venv | |
$pythonLibPath = Get-ChildItem -LiteralPath "$venvPath/lib" | Where-Object { $_.PSIsContainer } | Select-Object -First 1 | |
$sitePackagesPath = Join-Path -Path $pythonLibPath.FullName -ChildPath "site-packages" | |
Write-Host "Site-packages path: $sitePackagesPath" | |
# Use patchelf to adjust RPATH for all shared libraries in the virtual environment | |
Get-ChildItem -LiteralPath $sitePackagesPath -Filter *.so -Recurse | ForEach-Object { | |
$libPath = $_.FullName | |
Write-Host "Patching $libPath" | |
sudo patchelf --set-rpath '$ORIGIN' $libPath | |
} | |
shell: pwsh | |
- name: Compile HoloPatcher | |
if: ${{ (success() || failure()) && steps.holopatcher_deps.outputs.success == 'true' }} | |
run: | | |
$upxDir = $env:UPX_DIR | |
Write-Host "Using UPX directory at '$upxDir'" | |
$output = "" | |
$env:PYTHONOPTIMIZE = "1" | |
. ./compile/compile_holopatcher.ps1 -noprompt -venv_name .venv_holopatcher_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} -upx_dir $upxDir 2>&1 | ForEach-Object { | |
Write-Output $_.ToString() | |
$output += $_.ToString() + "`n" | |
if($_ -match 'ERROR:') { | |
$errorLines += $_.ToString() | |
} | |
} | |
$warningCount = 0 | |
$output -split "`n" | ForEach-Object { | |
if ($_ -match 'WARNING: Library not found: could not resolve' -or | |
$_ -match 'WARNING: Cannot find ' -or | |
$_ -match 'WARNING: lib not found:' -or | |
$_ -match 'WARNING: Tcl modules directory' -or | |
$_ -match 'WARNING: Failed to upx strip') { | |
$warningCount++ | |
} | |
} | |
if ($errorLines.Count -gt 0) { | |
$errorLines | ForEach-Object { Write-Error $_ } | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} elseif ($warningCount -ge 3) { | |
Write-Output "Many warnings raised, pyinstaller was probably unsuccessful." | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} else { | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=true" | |
} | |
shell: pwsh | |
- name: HoloPatcher - Create Static Binary | |
if: ${{ (success() || failure()) && runner.os == 'Disabled_Linux' && steps.holopatcher_deps.outputs.success == 'true' }} | |
run: | | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_holopatcher_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
& $pythonExePath -m pip install staticx | |
staticx ./dist/HoloPatcher ./dist/HoloPatcher-static | |
# Rename the static binary for clarity and consistency | |
Write-Output "./dist/HoloPatcher-static --> ./dist/HoloPatcher" | |
Move-Item -LiteralPath ./dist/HoloPatcher-static -Destination ./dist/HoloPatcher -Force | |
shell: pwsh | |
- name: Install BatchPatcher dependencies | |
if: ${{ success() || failure() }} | |
env: | |
MATRIX_ARCH: ${{ matrix.architecture }} | |
id: batchpatcher_deps | |
run: | # known pyinstaller versions that work with upx compressions, not all are available on all python versions. | |
try { | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_batchpatcher_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} -force_python_version ${{ matrix.python-version }} | |
& $pythonExePath -m pip install --upgrade pip | |
if ("${{ runner.os }}" -eq "Windows") { | |
if ("${{ matrix.python-version }}" -eq "3.12") { | |
pip install pyinstaller --prefer-binary -U | |
} elseif ("${{ matrix.python-version }}" -eq "3.11") { | |
pip install "pyinstaller==5.13.2" --prefer-binary | |
} else { | |
pip install "pyinstaller==5.4" --prefer-binary | |
} | |
} else { | |
pip install pyinstaller -U --prefer-binary | |
} | |
$output = "" | |
$errorLines = @() | |
. ./compile/deps_batchpatcher.ps1 -noprompt -venv_name .venv_batchpatcher_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} 2>&1 | ForEach-Object { | |
Write-Output $_.ToString() | |
$output += $_.ToString() + "`n" | |
if($_ -match 'ERROR:') { | |
$errorLines += $_.ToString() | |
} | |
} | |
if ($errorLines.Count -gt 0) { | |
$errorLines | ForEach-Object { Write-Error $_ } | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} else { | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=true" | |
} | |
} catch { | |
Write-Host -ForegroundColor Red "Detailed Error Report:" | |
Write-Host -ForegroundColor Red "Message: $($_.Exception.Message)" | |
# Attempt to provide a more detailed location of the error | |
if ($_.InvocationInfo -and $_.InvocationInfo.MyCommand) { | |
Write-Host -ForegroundColor Red "Command Name: $($_.InvocationInfo.MyCommand.Name)" | |
Write-Host -ForegroundColor Red "Script Name: $($_.InvocationInfo.ScriptName)" | |
Write-Host -ForegroundColor Red "Line Number: $($_.InvocationInfo.ScriptLineNumber)" | |
Write-Host -ForegroundColor Red "Line: $($_.InvocationInfo.Line)" | |
} else { | |
Write-Host -ForegroundColor Red "No invocation information available." | |
} | |
# Extract and display the script stack trace if available | |
if ($_.ScriptStackTrace) { | |
Write-Host -ForegroundColor Red "Script Stack Trace:" | |
Write-Host -ForegroundColor Red $_.ScriptStackTrace | |
} else { | |
Write-Host -ForegroundColor Red "No script stack trace available." | |
} | |
# Log the error to GitHub Actions output or another logging mechanism | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} | |
shell: pwsh | |
- name: BatchPatcher - Adjust RPATH for shared libraries in the virtual environment | |
if: ${{ (success() || failure()) && runner.os == 'Disabled_Linux' && steps.batchpatcher_deps.outputs.success == 'true' }} | |
run: | | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_batchpatcher_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
# Ensure patchelf is installed | |
sudo apt-get update && sudo apt-get install -y patchelf | |
# Find the virtual environment's site-packages directory | |
$venvPath = $env:VIRTUAL_ENV | |
Write-Host "Virtual environment path: $venvPath" | |
# Dynamically find the Python version directory inside the venv | |
$pythonLibPath = Get-ChildItem -LiteralPath "$venvPath/lib" | Where-Object { $_.PSIsContainer } | Select-Object -First 1 | |
$sitePackagesPath = Join-Path -Path $pythonLibPath.FullName -ChildPath "site-packages" | |
Write-Host "Site-packages path: $sitePackagesPath" | |
# Use patchelf to adjust RPATH for all shared libraries in the virtual environment | |
Get-ChildItem -LiteralPath $sitePackagesPath -Filter *.so -Recurse | ForEach-Object { | |
$libPath = $_.FullName | |
Write-Host "Patching $libPath" | |
sudo patchelf --set-rpath '$ORIGIN' $libPath | |
} | |
shell: pwsh | |
- name: Compile BatchPatcher | |
if: ${{ (success() || failure()) && steps.batchpatcher_deps.outputs.success == 'true' }} | |
run: | | |
$upxDir = $env:UPX_DIR | |
Write-Host "Using UPX directory at '$upxDir'" | |
$output = "" | |
$env:PYTHONOPTIMIZE = "1" | |
. ./compile/compile_batchpatcher.ps1 -noprompt -venv_name .venv_batchpatcher_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} -upx_dir $upxDir 2>&1 | ForEach-Object { | |
Write-Output $_.ToString() | |
$output += $_.ToString() + "`n" | |
if($_ -match 'ERROR:') { | |
$errorLines += $_.ToString() | |
} | |
} | |
$warningCount = 0 | |
$output -split "`n" | ForEach-Object { | |
if ($_ -match 'WARNING: Library not found: could not resolve' -or | |
$_ -match 'WARNING: Cannot find ' -or | |
$_ -match 'WARNING: lib not found:' -or | |
$_ -match 'WARNING: Tcl modules directory' -or | |
$_ -match 'WARNING: Failed to upx strip') { | |
$warningCount++ | |
} | |
} | |
if ($errorLines.Count -gt 0) { | |
$errorLines | ForEach-Object { Write-Error $_ } | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} elseif ($warningCount -ge 3) { | |
Write-Output "Many warnings raised, pyinstaller was probably unsuccessful." | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} else { | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=true" | |
} | |
shell: pwsh | |
- name: BatchPatcher - Create Static Binary | |
if: ${{ (success() || failure()) && runner.os == 'Disabled_Linux' && steps.batchpatcher_deps.outputs.success == 'true' }} | |
run: | | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_batchpatcher_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
& $pythonExePath -m pip install staticx | |
staticx ./dist/K_BatchPatcher ./dist/K_BatchPatcher-static | |
# Rename the static binary for clarity and consistency | |
Write-Output "./dist/K_BatchPatcher-static --> ./dist/K_BatchPatcher" | |
Move-Item -LiteralPath ./dist/K_BatchPatcher-static -Destination ./dist/K_BatchPatcher -Force | |
shell: pwsh | |
- name: Compile KotorDiff | |
if: ${{ success() || failure() }} | |
env: | |
MATRIX_ARCH: ${{ matrix.architecture }} | |
run: | | |
$upxDir = $env:UPX_DIR | |
Write-Host "Using UPX directory at '$upxDir'" | |
$env:PYTHONOPTIMIZE = "1" | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_kotordiff_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} -force_python_version ${{ matrix.python-version }} | |
& $pythonExePath -m pip install --upgrade pip | |
if ("${{ runner.os }}" -eq "Windows") { | |
if ("${{ matrix.python-version }}" -eq "3.12") { | |
pip install "pyinstaller==5.13.2" --prefer-binary | |
} elseif ("${{ matrix.python-version }}" -eq "3.11") { | |
pip install "pyinstaller==5.13.2" --prefer-binary | |
} else { | |
pip install "pyinstaller==5.4" --prefer-binary | |
} | |
} else { | |
pip install pyinstaller -U --prefer-binary | |
} | |
pip install -r Tools/KotorDiff/requirements.txt --prefer-binary | |
$output = "" | |
. ./compile/compile_kotordiff.ps1 -noprompt -venv_name .venv_kotordiff_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} -upx_dir $upxDir 2>&1 | ForEach-Object { | |
Write-Output $_.ToString() | |
$output += $_.ToString() + "`n" | |
if($_ -match 'ERROR:') { | |
$errorLines += $_.ToString() | |
} | |
} | |
$warningCount = 0 | |
$output -split "`n" | ForEach-Object { | |
if ($_ -match 'WARNING: Library not found: could not resolve' -or | |
$_ -match 'WARNING: Cannot find ' -or | |
$_ -match 'WARNING: lib not found:' -or | |
$_ -match 'WARNING: Tcl modules directory' -or | |
$_ -match 'WARNING: Failed to upx strip') { | |
$warningCount++ | |
} | |
} | |
if ($errorLines.Count -gt 0) { | |
$errorLines | ForEach-Object { Write-Error $_ } | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} elseif ($warningCount -ge 3) { | |
Write-Output "Many warnings raised, pyinstaller was probably unsuccessful." | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} else { | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=true" | |
} | |
shell: pwsh | |
- name: KotorDiff - Create Static Binary | |
if: ${{ (success() || failure()) && runner.os == 'Linux' }} | |
run: | | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_kotordiff_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
& $pythonExePath -m pip install staticx | |
staticx ./dist/KotorDiff ./dist/KotorDiff-static | |
# Rename the static binary for clarity and consistency | |
Write-Output "./dist/KotorDiff-static --> ./dist/KotorDiff" | |
Move-Item -LiteralPath ./dist/KotorDiff-static -Destination ./dist/KotorDiff -Force | |
shell: pwsh | |
- name: Compile GUIDuplicator | |
if: ${{ success() || failure() }} | |
env: | |
MATRIX_ARCH: ${{ matrix.architecture }} | |
run: | | |
$upxDir = $env:UPX_DIR | |
Write-Host "Using UPX directory at '$upxDir'" | |
$env:PYTHONOPTIMIZE = "1" | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_guiduplicator_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} -force_python_version ${{ matrix.python-version }} | |
& $pythonExePath -m pip install --upgrade pip | |
if ("${{ runner.os }}" -eq "Windows") { | |
if ("${{ matrix.python-version }}" -eq "3.12") { | |
pip install "pyinstaller==5.13.2" --prefer-binary | |
} elseif ("${{ matrix.python-version }}" -eq "3.11") { | |
pip install "pyinstaller==5.13.2" --prefer-binary | |
} else { | |
pip install "pyinstaller==5.4" --prefer-binary | |
} | |
} else { | |
pip install pyinstaller -U --prefer-binary | |
} | |
pip install -r Tools/GuiDuplicator/requirements.txt --prefer-binary | |
$output = "" | |
. ./compile/compile_gui_duplicator.ps1 -noprompt -venv_name .venv_guiduplicator_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} -upx_dir $upxDir 2>&1 | ForEach-Object { | |
Write-Output $_.ToString() | |
if($_ -match 'ERROR:') { | |
$errorLines += $_.ToString() | |
} | |
} | |
$warningCount = 0 | |
$output -split "`n" | ForEach-Object { | |
if ($_ -match 'WARNING: Library not found: could not resolve' -or | |
$_ -match 'WARNING: Cannot find ' -or | |
$_ -match 'WARNING: lib not found:' -or | |
$_ -match 'WARNING: Tcl modules directory' -or | |
$_ -match 'WARNING: Failed to upx strip') { | |
$warningCount++ | |
} | |
} | |
if ($errorLines.Count -gt 0) { | |
$errorLines | ForEach-Object { Write-Error $_ } | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} elseif ($warningCount -ge 3) { | |
Write-Output "Many warnings raised, pyinstaller was probably unsuccessful." | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=false" | |
exit 1 | |
} else { | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "success=true" | |
} | |
shell: pwsh | |
- name: GUIDuplicator - Create Static Binary | |
if: ${{ (success() || failure()) && runner.os == 'Linux' }} | |
run: | | |
. ./install_python_venv.ps1 -noprompt -venv_name .venv_guiduplicator_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
& $pythonExePath -m pip install staticx | |
staticx ./dist/GuiDuplicator ./dist/GuiDuplicator-static | |
# Rename the static binary for clarity and consistency | |
Write-Output "./dist/GuiDuplicator-static --> ./dist/GuiDuplicator" | |
Move-Item -LiteralPath ./dist/GuiDuplicator-static -Destination ./dist/GuiDuplicator -Force | |
shell: pwsh | |
- name: Upload compiled binaries attempt 1 | |
if: ${{ success() || failure() }} | |
id: upload_attempt_1 | |
uses: actions/upload-artifact@v4 | |
with: | |
name: publish_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
path: ./dist/** | |
retention-days: 90 | |
continue-on-error: true | |
- name: Upload compiled binaries attempt 2 | |
id: upload_attempt_2 | |
if: ${{ (success() || failure()) && steps.upload_attempt_1.outcome == 'failure' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: publish_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
path: ./dist/** | |
retention-days: 90 | |
continue-on-error: true | |
- name: Upload compiled binaries attempt 3 | |
id: upload_attempt_3 | |
if: ${{ (success() || failure()) && steps.upload_attempt_2.outcome == 'failure' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: publish_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
path: ./dist/** | |
retention-days: 90 | |
continue-on-error: true | |
- name: Upload compiled binaries attempt 4 | |
id: upload_attempt_4 | |
if: ${{ (success() || failure()) && steps.upload_attempt_3.outcome == 'failure' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: publish_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
path: ./dist/** | |
retention-days: 90 | |
continue-on-error: true | |
- name: Upload compiled binaries attempt 5 | |
id: upload_attempt_5 | |
if: ${{ (success() || failure()) && steps.upload_attempt_4.outcome == 'failure' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: publish_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} | |
path: ./dist/** | |
retention-days: 90 | |
package: # The goal of this job is to repackage by toolname, rather than all tools by os_pyversion_arch | |
needs: build # do not start this job until all 'build' jobs complete | |
if: ${{ success() || failure() }} | |
runs-on: ubuntu-latest | |
outputs: | |
filesToArchive: ${{ steps.set-matrix.outputs.matrixJson }} | |
steps: | |
- name: Download all artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
path: published_workflow_builds/ | |
pattern: publish_* | |
- name: Re-package artifacts by Python version and architecture | |
shell: pwsh | |
run: | | |
$here_dirpath = (Get-Location) | |
Write-Output "here: '$here_dirpath'" | |
$packagedArtifactsPath = Join-Path -Path $here_dirpath -ChildPath "packaged_artifacts" | |
New-Item -ItemType Directory -Force -Path $packagedArtifactsPath | |
# Navigate to the directory with downloaded artifacts | |
Set-Location -Path "published_workflow_builds" | |
$artifactNames = New-Object 'System.Collections.Generic.HashSet[string]' | |
# Iterate through each os_pythonversion_arch folder. | |
Get-ChildItem -Filter "publish_*" | ForEach-Object { | |
$matrixPackagePath = $_.FullName | |
Write-Output "Found matrix package '$matrixPackagePath'" | |
$os, $python_or_pypy, $pythonVersion, $architecture = $_.BaseName -replace '^publish_', '' -split '_' | |
$shortOsName = $os | |
if ($os -eq "ubuntu-20.04" -or $os -eq "ubuntu-22.04" -or $os -eq "ubuntu-latest") { | |
$shortOsName = "Linux" | |
} elseif ($os -eq "macos-11" -or $os -eq "macos-12" -or $os -eq "macos-latest") { | |
$shortOsName = "Mac" | |
} elseif ($os -eq "windows-2019" -or $os -eq "windows-2022" -or $os -eq "windows-latest") { | |
$shortOsName = "Win" | |
} | |
# Iterate through each tool in the folder | |
Get-ChildItem -LiteralPath $matrixPackagePath | ForEach-Object { | |
$toolExePath = $_.FullName | |
$toolFileName = $_.Name | |
$fileBaseName = [IO.Path]::GetFileNameWithoutExtension($_.Name) | |
$fileExtension = $_.Extension | |
$outerArchiveName = "$fileBaseName`_$pythonVersion" | |
$outerZipPath = Join-Path -Path $packagedArtifactsPath -ChildPath $outerArchiveName | |
$osSpecificArchiveName = "$fileBaseName`_$shortOsName-$architecture" | |
$osSpecificArchivePath = Join-Path -Path $outerZipPath -ChildPath $osSpecificArchiveName | |
Write-Output " ToolFileName: '$toolFileName'" | |
Write-Output " Tool original filepath: '$toolExePath'" | |
Write-Output "outerArchiveName: '$outerArchiveName'" | |
Write-Output " - osSpecificArchiveName: '$osSpecificArchiveName'" | |
Write-Output "outerZipPath: '$outerZipPath'" | |
Write-Output " - osSpecificArchivePath: '$osSpecificArchivePath'" | |
New-Item -ItemType Directory -Force -Path $outerZipPath | |
chmod 777 -R $toolExePath | |
$toolExeParentDirPath = Split-Path -Parent $toolExePath | |
Write-Output "Creating archive for '$toolFileName' at '$toolExeParentDirPath'..." | |
Write-Output ("Push-Location to start in '$toolExeParentDirPath' (originally at '$(Get-Location)')") | |
Push-Location -Path $toolExeParentDirPath | |
# Archive the tool by os identifier. | |
if ((-not $fileExtension) -or (-not $fileExtension.Trim()) -or ($fileExtension.ToLower().Trim() -eq ".app")) { | |
$osSpecificArchivePath = "$osSpecificArchivePath.tar.gz" | |
if (Test-Path $toolExePath -PathType Container -ErrorAction SilentlyContinue) { # It's a directory | |
tar -czf "$osSpecificArchivePath" -C "$toolExePath" . | |
} else { # It's a file | |
tar -czf "$osSpecificArchivePath" -C "$toolExeParentDirPath" $toolFileName | |
} | |
} else { | |
$osSpecificArchivePath = "$osSpecificArchivePath.zip" | |
zip -r -9 "$osSpecificArchivePath" $toolFileName | |
} | |
Pop-Location | |
Write-Output ("Pop-Location to return to $(Get-Location) (was pushed to '$toolExeParentDirPath')") | |
Write-Output "Compressed archive saved to '$osSpecificArchivePath'" | |
chmod 777 -R "$osSpecificArchivePath" | |
$artifactNames.Add($outerArchiveName) | |
} | |
} | |
# Save artifact names to a file | |
$artifactNames | Out-File -FilePath "../artifact-names.txt" -Encoding UTF8 | |
# use for debug | |
# Get-ChildItem -Force | ForEach-Object { | |
# $size = if ($_.PSIsContainer) { "N/A" } else { $_.Length } | |
# $attrs = $_.Attributes.ToString() -replace 'ReadOnly', 'RO' -replace 'Hidden', 'H' -replace 'System', 'S' -replace 'Archive', 'A' -replace 'Directory', 'D' -replace ', ', '|' | |
# [PSCustomObject]@{ | |
# Name = $_.Name | |
# Size = $size | |
# Attributes = $attrs | |
# } | |
# } | Format-Table -AutoSize | |
# Navigate back to the root of the workspace | |
Set-Location -Path "../" | |
- name: Generate matrix for uploading | |
if: ${{ success() || failure() }} | |
id: set-matrix | |
shell: pwsh | |
run: | | |
$artifactNames = Get-Content 'artifact-names.txt' -ReadCount 0 | |
# Initialize an array to hold the artifact names directly | |
$matrixArray = @() | |
foreach ($name in $artifactNames) { | |
if (-not [string]::IsNullOrEmpty($name)) { | |
Write-Host "Processing artifact name: $name" | |
# Trim the name and add directly to the array | |
$matrixArray += $name.trim() | |
} | |
} | |
# Convert the array directly to JSON | |
$jsonMatrix = $matrixArray | ConvertTo-Json -Depth 5 -Compress | |
# Use a single line of JSON for the matrix to avoid issues | |
$singleLineJsonMatrix = $jsonMatrix -replace "`r", "" | |
$singleLineJsonMatrix = $singleLineJsonMatrix -replace "`n", "" | |
Write-Host "Matrix JSON:" | |
Write-Host $singleLineJsonMatrix | |
echo "matrixJson<<EOF" >> $env:GITHUB_OUTPUT | |
echo $singleLineJsonMatrix >> $env:GITHUB_OUTPUT | |
echo "EOF" >> $env:GITHUB_OUTPUT | |
- name: Upload all repackages for next job | |
if: ${{ success() || failure() }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: all_tool_dists_onearchive | |
path: packaged_artifacts/** | |
retention-days: 1 # only used for the next job. | |
compression-level: 0 | |
upload: | |
needs: package | |
if: ${{ success() || failure() }} | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
artifactb: ${{ fromJson(needs.package.outputs.filesToArchive) }} | |
steps: | |
- name: Download repackages from package job | |
if: ${{ success() || failure() }} | |
uses: actions/download-artifact@v4 | |
with: | |
path: all_tool_dists_onearchive | |
pattern: all_tool_dists* | |
- name: Upload re-packaged artifact | |
if: ${{ success() || failure() }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ matrix.artifactb }} | |
path: all_tool_dists_onearchive/all_tool_dists_onearchive/${{ matrix.artifactb }} | |
compression-level: 9 | |
if-no-files-found: error |