From 74eada1b9c7393eeaab1f1db579e0729fbd4ae9c Mon Sep 17 00:00:00 2001 From: Benjamin Auquite Date: Fri, 30 Aug 2024 06:01:31 -0500 Subject: [PATCH] create release workflow for gui converter --- .github/workflows/release_guiconverter.yml | 544 ++++++++++++++++++ .../utility/system/win32/com/interfaces.py | 2 +- .../src/gui_converter/__main__.py | 4 +- ...converter.ps1 => compile_guiconverter.ps1} | 0 4 files changed, 547 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/release_guiconverter.yml rename compile/{compile_gui_converter.ps1 => compile_guiconverter.ps1} (100%) mode change 100755 => 100644 diff --git a/.github/workflows/release_guiconverter.yml b/.github/workflows/release_guiconverter.yml new file mode 100644 index 000000000..07ce0a924 --- /dev/null +++ b/.github/workflows/release_guiconverter.yml @@ -0,0 +1,544 @@ +name: GuiConverter 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"]' + UPX_VERSION: '4.2.2' + +on: + push: + tags: + - '*guiconverter*' + 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<> $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<> $env:GITHUB_OUTPUT + echo $singleLineJson >> $env:GITHUB_OUTPUT + echo "EOF" >> $env:GITHUB_OUTPUT + + $singleLineJson = '${{ env.ARCHITECTURES_JSON }}' -replace "`r", "" -replace "`n", "" + echo "architecture<> $env:GITHUB_OUTPUT + echo $singleLineJson >> $env:GITHUB_OUTPUT + echo "EOF" >> $env:GITHUB_OUTPUT + + $singleLineJson = '${{ env.INTERPRETERS_JSON }}' -replace "`r", "" -replace "`n", "" + echo "python-pypy<> $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', 'pyqt6', 'pyside2', 'pyside6'] + 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' + + 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 == 'Windows' + 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 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 GuiConverter dependencies + if: ${{ success() || failure() }} + env: + MATRIX_ARCH: ${{ matrix.architecture }} + id: guiconverter_deps + run: | # known pyinstaller versions that work with upx compressions, not all are available on all python versions. + try { + $env:LD_LIBRARY_PATH = "/usr/local/lib:$env:LD_LIBRARY_PATH" + . ./install_python_venv.ps1 -noprompt -venv_name .venv_guiconverter_${{ 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 + } + pip install comtypes + } else { + pip install pyinstaller -U --prefer-binary + } + 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: GuiConverter - Adjust RPATH for shared libraries in the virtual environment + if: ${{ (success() || failure()) && runner.os == 'Disabled_Linux' && steps.guiconverter_deps.outputs.success == 'true' }} + run: | + . ./install_python_venv.ps1 -noprompt -venv_name .venv_guiconverter_${{ 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 GuiConverter + if: ${{ (success() || failure()) && steps.guiconverter_deps.outputs.success == 'true' }} + run: | + $env:LD_LIBRARY_PATH = "/usr/local/lib:$env:LD_LIBRARY_PATH" + $upxDir = $env:UPX_DIR + Write-Host "Using UPX directory at '$upxDir'" + $output = "" + $env:PYTHONOPTIMIZE = "1" + . ./compile/compile_guiconverter.ps1 -noprompt -venv_name .venv_guiconverter_${{ 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: GuiConverter - Create Static Binary + if: ${{ (success() || failure()) && runner.os == 'Disabled_Linux' && steps.guiconverter_deps.outputs.success == 'true' }} + run: | + . ./install_python_venv.ps1 -noprompt -venv_name .venv_guiconverter_${{ matrix.os }}_${{ matrix.python_pypy }}_${{ matrix.python-version }}_${{ matrix.architecture }} + & $pythonExePath -m pip install staticx + staticx ./dist/GuiConverter ./dist/GuiConverter-static + # Rename the static binary for clarity and consistency + Write-Output "./dist/GuiConverter-static --> ./dist/GuiConverter" + Move-Item -LiteralPath ./dist/GuiConverter-static -Destination ./dist/GuiConverter -Force + shell: pwsh + + - name: Upload GuiConverter binaries attempt 1 + if: ${{ success() || failure() }} + id: upload_attempt_1 + uses: actions/upload-artifact@v4 + with: + name: GuiConverter_${{ runner.os }}_${{ matrix.architecture }} + path: ./dist/** + retention-days: 90 + continue-on-error: true + + - name: Upload GuiConverter binaries attempt 2 + id: upload_attempt_2 + if: ${{ (success() || failure()) && steps.upload_attempt_1.outcome == 'failure' }} + uses: actions/upload-artifact@v4 + with: + name: GuiConverter_${{ runner.os }}_${{ matrix.architecture }} + path: ./dist/** + retention-days: 90 + continue-on-error: true + + - name: Upload GuiConverter binaries attempt 3 + id: upload_attempt_3 + if: ${{ (success() || failure()) && steps.upload_attempt_2.outcome == 'failure' }} + uses: actions/upload-artifact@v4 + with: + name: GuiConverter_${{ runner.os }}_${{ matrix.architecture }} + path: ./dist/** + retention-days: 90 + continue-on-error: true + + - name: Upload GuiConverter binaries attempt 4 + id: upload_attempt_4 + if: ${{ (success() || failure()) && steps.upload_attempt_3.outcome == 'failure' }} + uses: actions/upload-artifact@v4 + with: + name: GuiConverter_${{ runner.os }}_${{ matrix.architecture }} + path: ./dist/** + retention-days: 90 + continue-on-error: true + + - name: Upload GuiConverter binaries attempt 5 + id: upload_attempt_5 + if: ${{ (success() || failure()) && steps.upload_attempt_4.outcome == 'failure' }} + uses: actions/upload-artifact@v4 + with: + name: GuiConverter_${{ runner.os }}_${{ 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: GuiConverter_* + + - 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 'guiconverter' + 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 'guiconverter', then pick the most recent one based on how they're listed + $tag = git tag --list '*guiconverter*' | Select-Object -Last 1 + } else { + git fetch --depth=1 origin '+refs/tags/*:refs/tags/*' + # Get all tags ending with 'guiconverter', then pick the most recent one based on how they're listed + $tag = git tag --list '*guiconverter*' | Select-Object -Last 1 + } + if (-not $tag) { + echo "No matching tag found ending with 'guiconverter'." + 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 'guiconverter', 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 diff --git a/Libraries/Utility/src/utility/system/win32/com/interfaces.py b/Libraries/Utility/src/utility/system/win32/com/interfaces.py index 821320483..07a552af7 100644 --- a/Libraries/Utility/src/utility/system/win32/com/interfaces.py +++ b/Libraries/Utility/src/utility/system/win32/com/interfaces.py @@ -952,7 +952,7 @@ def AddRef(self) -> ULONG: return ULONG(-1) def Release(self) -> ULONG: return ULONG(-1) - def Show(self, hwndOwner: HWND | int) -> HRESULT: + def Show(self, hwndOwner: HWND | int) -> HRESULT: # noqa: N803 return S_OK def SetFileTypes(self, cFileTypes: c_uint | int, rgFilterSpec: Array[COMDLG_FILTERSPEC]) -> HRESULT: # noqa: N803 return S_OK diff --git a/Tools/GuiConverter/src/gui_converter/__main__.py b/Tools/GuiConverter/src/gui_converter/__main__.py index 584546e84..dacd85098 100644 --- a/Tools/GuiConverter/src/gui_converter/__main__.py +++ b/Tools/GuiConverter/src/gui_converter/__main__.py @@ -319,7 +319,7 @@ def get_lookup_function() -> Callable[[str], list[str]]: return lookup_function if os.name == "nt": def lookup_function(title: str) -> list[str]: - return open_file_and_folder_dialog(title=title) or [] + return open_file_and_folder_dialog(title=title, allow_multiple_selection=True) or [] else: choice = input("Do you want to pick a path using a ui-based file/directory picker? (y/N)").strip().lower() if not choice or choice == "y": @@ -337,7 +337,7 @@ def lookup_function(title: str) -> str: result, unknown = parser.parse_known_args() while True: - result.input = result.input or (unknown if len(unknown) > 0 else None) or askopenfilenames(title="Select K1/TSL GUI file(s) to convert") + result.input = result.input or (unknown if len(unknown) > 0 else None) or get_lookup_function()("Select K1/TSL GUI file(s) to convert") if not result.input or not any(result.input): if not askretrycancel("error: You cancelled the browse file dialog.", "You must choose at least one .gui file!"): sys.exit() diff --git a/compile/compile_gui_converter.ps1 b/compile/compile_guiconverter.ps1 old mode 100755 new mode 100644 similarity index 100% rename from compile/compile_gui_converter.ps1 rename to compile/compile_guiconverter.ps1