Toolset Release #74
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: Toolset Release | |
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"]' | |
ARCHITECTURES_JSON: '["x86", "x64"]' | |
INTERPRETERS_JSON: '["python"]' | |
QT_VERSIONS_JSON: '["PyQt5"]' | |
UPX_VERSION: '4.2.2' | |
on: | |
push: | |
tags: | |
- '*toolset*' | |
workflow_dispatch: | |
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 | |
$singleLineJson = '${{ env.QT_VERSIONS_JSON }}' -replace "`r", "" -replace "`n", "" | |
echo "qt_version<<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: ${{ fromJson(needs.setup.outputs.qt_version) }} | |
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' | |
- qt_version: 'PyQt6' | |
architecture: x86 | |
- qt_version: 'PySide6' | |
architecture: x86 | |
outputs: | |
matrix-os: ${{ toJson(matrix.os) }} | |
matrix-python-version: ${{ toJson(matrix.python-version) }} | |
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 | |
- 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" | |
# Write to the GITHUB_OUTPUT environment file | |
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" | |
# Ensure upx-dir exists; create it if it doesn't | |
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: Set QT_API for macOS | |
if: runner.os == 'macOS' | |
run: echo "QT_API=${{ matrix.qt_version }}" >> $GITHUB_ENV | |
shell: bash | |
- name: Install Holocron Toolset dependencies | |
if: ${{ success() || failure() }} | |
env: | |
MATRIX_ARCH: ${{ matrix.architecture }} | |
QT_API: ${{ matrix.qt_version }} | |
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.13.2" --prefer-binary | |
} | |
pip install pywin32 --prefer-binary -U | |
} else { | |
pip install pyinstaller -U --prefer-binary | |
} | |
$env:QT_API = "${{ 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" | |
} | |
pip install "setuptools==69.5.1" # 70.0.0 and higher breaks pyinstaller | |
pip install qdarkstyle -U | |
} 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: HolocronToolset - Adjust RPATH for shared libraries in the virtual environment | |
if: ${{ (success() || failure()) && runner.os == 'Disabled_Linux' && steps.toolset_deps.outputs.success == 'true' }} | |
env: | |
MATRIX_ARCH: ${{ matrix.architecture }} | |
QT_API: ${{ matrix.qt_version }} | |
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: Compile Holocron Toolset | |
if: ${{ (success() || failure()) && steps.toolset_deps.outputs.success == 'true' }} | |
env: | |
MATRIX_ARCH: ${{ matrix.architecture }} | |
QT_API: ${{ matrix.qt_version }} | |
run: | | |
$upxDir = $env:UPX_DIR | |
Write-Host "Using UPX directory at '$upxDir'" | |
$output = "" | |
$env:PYTHONOPTIMIZE = "1" | |
$env:QT_API = "${{ matrix.qt_version }}" | |
. ./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: Upload HolocronToolset binaries attempt 1 | |
if: ${{ success() || failure() }} | |
id: upload_attempt_1 | |
uses: actions/upload-artifact@v4 | |
with: | |
name: HolocronToolset_${{ runner.os }}_${{ matrix.qt_version}}_${{ matrix.architecture }} | |
path: ./dist/** | |
retention-days: 90 | |
continue-on-error: true | |
- name: Upload HolocronToolset binaries attempt 2 | |
id: upload_attempt_2 | |
if: ${{ (success() || failure()) && steps.upload_attempt_1.outcome == 'failure' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: HolocronToolset_${{ runner.os }}_${{ matrix.qt_version}}_${{ matrix.architecture }} | |
path: ./dist/** | |
retention-days: 90 | |
continue-on-error: true | |
- name: Upload HolocronToolset binaries attempt 3 | |
id: upload_attempt_3 | |
if: ${{ (success() || failure()) && steps.upload_attempt_2.outcome == 'failure' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: HolocronToolset_${{ runner.os }}_${{ matrix.qt_version}}_${{ matrix.architecture }} | |
path: ./dist/** | |
retention-days: 90 | |
continue-on-error: true | |
- name: Upload HolocronToolset binaries attempt 4 | |
id: upload_attempt_4 | |
if: ${{ (success() || failure()) && steps.upload_attempt_3.outcome == 'failure' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: HolocronToolset_${{ runner.os }}_${{ matrix.qt_version}}_${{ matrix.architecture }} | |
path: ./dist/** | |
retention-days: 90 | |
continue-on-error: true | |
- name: Upload HolocronToolset binaries attempt 5 | |
id: upload_attempt_5 | |
if: ${{ (success() || failure()) && steps.upload_attempt_4.outcome == 'failure' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: HolocronToolset_${{ runner.os }}_${{ matrix.qt_version}}_${{ matrix.architecture }} | |
path: ./dist/** | |
retention-days: 90 | |
package: | |
needs: build # do not start this job until all 'build' jobs complete | |
if: ${{ success() || failure() }} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Download all artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
path: published_workflow_builds/ | |
pattern: HolocronToolset_* | |
- name: Compress into archives | |
run: | | |
$originalDir = Get-Location | |
$sourceFolder = Join-Path -Path $originalDir -ChildPath "published_workflow_builds" | |
Set-Location $sourceFolder | |
Get-ChildItem -LiteralPath "." -Directory | ForEach-Object { | |
$folderName = $_.Name | |
$archiveName = "$folderName.zip" | |
zip -r -9 $archiveName $folderName | |
} | |
Set-Location $originalDir | |
shell: pwsh | |
- name: Determine Release Tag Ending with 'toolset' | |
id: get_tag | |
run: | | |
if ($env:GITHUB_EVENT_NAME -eq "workflow_dispatch") { | |
git fetch --depth=1 origin '+refs/tags/*:refs/tags/*' | |
# Get all tags ending with 'toolset', then pick the most recent one based on how they're listed | |
$tag = git tag --list '*toolset*' | Select-Object -Last 1 | |
} else { | |
git fetch --depth=1 origin '+refs/tags/*:refs/tags/*' | |
# Get all tags ending with 'toolset', then pick the most recent one based on how they're listed | |
$tag = git tag --list '*toolset*' | Select-Object -Last 1 | |
} | |
if (-not $tag) { | |
echo "No matching tag found ending with 'toolset'." | |
git tag --list | |
exit 1 | |
} | |
echo "tag=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Append | |
shell: pwsh | |
- name: Release | |
uses: softprops/action-gh-release@v2 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
tag_name: ${{ steps.get_tag.outputs.tag }} | |
files: "published_workflow_builds/*.zip" | |
fail_on_unmatched_files: true | |
target_commitish: ${{ github.event_name == 'workflow_dispatch' && github.ref_name || github.head_ref }} | |
- name: Determine Release ID for fallback upload. | |
if: ${{ failure() }} | |
id: get_release_id | |
run: | | |
# Filter tags ending with 'toolset', sort them by date, and pick the most recent one | |
$uri = "https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ steps.get_tag.outputs.tag }}" | |
$headers = @{Authorization = "token ${{ secrets.GITHUB_TOKEN }}"} | |
$response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers | |
$releaseId = $response.id | |
echo "RELEASE_ID=$releaseId" | Out-File -FilePath $env:GITHUB_ENV -Append | |
shell: pwsh | |
- name: Upload Archive to Release | |
if: ${{ failure() }} | |
run: | | |
try { | |
Add-Type -TypeDefinition @" | |
using System; | |
using System.Net.Http; | |
using System.Net.Http.Headers; | |
using System.Threading.Tasks; | |
public class GitHubUploader { | |
public static async Task UploadFileAsync(string filePath, string uploadUrl, string token) { | |
using (var client = new HttpClient()) { | |
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); | |
using (var content = new MultipartFormDataContent()) { | |
var fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes(filePath)); | |
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream"); | |
content.Add(fileContent, "file", System.IO.Path.GetFileName(filePath)); | |
var response = await client.PostAsync(uploadUrl, content); | |
if (!response.IsSuccessStatusCode) { | |
throw new ApplicationException(await response.Content.ReadAsStringAsync()); | |
} | |
} | |
} | |
} | |
} | |
"@ | |
$archivePath = "published_workflow_builds/*.zip" | |
$releaseId = $env:RELEASE_ID | |
$token = "${{ secrets.GITHUB_TOKEN }}"" | |
Get-ChildItem -LiteralPath $archivePath | ForEach-Object { | |
$filePath = $_.FullName | |
$fileName = $_.Name | |
$uploadUrl = "https://uploads.github.com/repos/$env:GITHUB_REPOSITORY/releases/$releaseId/assets?name=$fileName&label=$fileName" | |
try { | |
Write-Host "Attempting to upload $fileName" | |
[GitHubUploader]::UploadFileAsync($filePath, $uploadUrl, $token).GetAwaiter().GetResult() | |
Write-Host "Upload successful: $fileName" | |
} catch { | |
Write-Host "Failed to upload $fileName : $($_.Exception.Message)" | |
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." | |
} | |
} | |
} | |
} 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 |