From 9fdbcf1bde564717f49ba67c2231a7e2eb880b04 Mon Sep 17 00:00:00 2001 From: Loren Eteval Date: Sun, 23 Aug 2026 17:05:30 +0800 Subject: [PATCH] Fix workflow Signed-off-by: Loren Eteval --- .github/workflows/deploy-pypi.yml | 178 +++++++++++++++++++++++++----- Deploy.py | 36 +++--- pyproject.toml | 2 +- requirements.txt | 2 +- 4 files changed, 173 insertions(+), 45 deletions(-) diff --git a/.github/workflows/deploy-pypi.yml b/.github/workflows/deploy-pypi.yml index febdbe1..042e836 100644 --- a/.github/workflows/deploy-pypi.yml +++ b/.github/workflows/deploy-pypi.yml @@ -80,7 +80,6 @@ jobs: deploy-binaries: name: Deploy ${{ matrix.id }} on ${{ matrix.os }} Python ${{ matrix.python-version }} runs-on: ${{ matrix.os }} - continue-on-error: true strategy: fail-fast: false matrix: @@ -135,6 +134,7 @@ jobs: GO_WIN7_VERSION: "1.26.7" NUITKA_VERSION: "4.1.3" WIX_VERSION: "6.0.2" + WIX_INSTALLER_SHA256: "A8A5CC7443353CEF3AB900C60CD7A3A5EE601746319D104AC7B12AD0CED2345C" steps: - uses: actions/checkout@v7 - name: Install macOS dependencies @@ -154,38 +154,67 @@ jobs: sudo apt install -y libxcb-cursor0 qt6-base-dev patchelf ccache zlib1g-dev sudo apt install -y flatpak flatpak-builder elfutils patchelf sudo apt install -y rpm - echo "QMAKE=$(which qmake6)" >> $GITHUB_ENV flatpak remote-add --if-not-exists --user flathub https://flathub.org/repo/flathub.flatpakrepo flatpak update flatpak install -y flathub org.kde.Platform//6.8 org.kde.Sdk//6.8 if [ "$RUNNER_ARCH" == "X64" ]; then - linuxdeploy_arch="x86_64" + appimage_arch="x86_64" elif [ "$RUNNER_ARCH" == "ARM64" ]; then - linuxdeploy_arch="aarch64" + appimage_arch="aarch64" else echo "Unknown runner architecture: $RUNNER_ARCH" exit 1 fi - echo "linuxdeploy architecture is $linuxdeploy_arch" + echo "appimagetool architecture is $appimage_arch" - linuxdeploy_name=".linuxdeploy-bin" - mkdir ${linuxdeploy_name} - echo "${PWD}/${linuxdeploy_name}" >> $GITHUB_PATH - wget -P ${linuxdeploy_name} https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-${linuxdeploy_arch}.AppImage - wget -P ${linuxdeploy_name} https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/latest/download/linuxdeploy-plugin-qt-${linuxdeploy_arch}.AppImage - wget -P ${linuxdeploy_name} https://github.com/AppImage/appimagetool/releases/latest/download/appimagetool-${linuxdeploy_arch}.AppImage - chmod +x ${linuxdeploy_name}/* + appimage_tools=".appimage-tools" + mkdir ${appimage_tools} + echo "${PWD}/${appimage_tools}" >> $GITHUB_PATH + wget -P ${appimage_tools} https://github.com/AppImage/appimagetool/releases/latest/download/appimagetool-${appimage_arch}.AppImage + chmod +x ${appimage_tools}/* if: runner.os == 'Linux' - name: Install Windows dependencies + shell: pwsh run: | - dotnet tool install --global wix --version "${WIX_VERSION}" - echo "$HOME/.dotnet/tools" >> $GITHUB_PATH + $toolsetArchitecture = switch ($env:RUNNER_ARCH) { + 'X64' { 'x64' } + 'ARM64' { 'arm64' } + default { throw "Unknown runner architecture: $env:RUNNER_ARCH" } + } + + $installer = Join-Path $env:RUNNER_TEMP 'wix-cli-x64.msi' + $installerUrl = "https://github.com/wixtoolset/wix/releases/download/v$env:WIX_VERSION/wix-cli-x64.msi" + Invoke-WebRequest -Uri $installerUrl -OutFile $installer + + $installerHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $installer).Hash + + if ($installerHash -ne $env:WIX_INSTALLER_SHA256) { + throw "Unexpected WiX installer SHA-256: $installerHash" + } + + $msi = Start-Process msiexec.exe -ArgumentList @( + '/i', + $installer, + '/quiet', + '/norestart', + '/log', + (Join-Path $env:RUNNER_TEMP 'wix-install.log') + ) -WindowStyle Hidden -Wait -PassThru + + if ($msi.ExitCode -notin @(0, 3010)) { + throw "WiX installation failed with exit code $($msi.ExitCode)" + } + + $toolsetRoot = 'C:\Program Files\WiX Toolset v6.0\bin' + $toolsetRoot | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + (Join-Path $toolsetRoot $toolsetArchitecture) | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append if: runner.os == 'Windows' - name: Check Windows dependencies run: | wix --version - wix extension add "WixToolset.UI.wixext/${WIX_VERSION}" + wix extension add -g "WixToolset.UI.wixext/${WIX_VERSION}" + wix extension list -g if: runner.os == 'Windows' - name: Set up Python for Windows7 uses: LorenEteval/setup-python-win7@v1 @@ -247,8 +276,8 @@ jobs: python -m pip install setuptools wheel python - <<'PY' - from pathlib import Path import re + from pathlib import Path excluded = { 'pyside6-addons', @@ -258,6 +287,7 @@ jobs: 'hysteria2', 'tun2socks', } + requirements = [] for line in Path('requirements.txt').read_text(encoding='utf-8').splitlines(): @@ -292,7 +322,9 @@ jobs: fi python -m pip install -r .binary-requirements.txt + python -m pip install "Nuitka==${NUITKA_VERSION}" imageio requests + python -c "import importlib.metadata; print('zxing-cpp', importlib.metadata.version('zxing-cpp'))" python -c "from PySide6 import QtCore; print(f'PySide6/Qt {QtCore.__version__}')" - name: Install patched Go for Windows7 run: | @@ -309,6 +341,11 @@ jobs: echo "${go_root}\\bin" >> $GITHUB_PATH if: matrix.id == 'windows-win7-amd64' - name: Build Windows7 bindings from source with patched Go + env: + CC: gcc + CXX: g++ + CMAKE_BUILD_PARALLEL_LEVEL: "2" + GOPROXY: https://proxy.golang.org,direct run: | command -v go go version @@ -316,16 +353,45 @@ jobs: command -v gcc gcc -dumpmachine + short_temp="$RUNNER_TEMP/w7" + mkdir -p "$short_temp" + short_temp="$(cygpath -w "$short_temp")" + export TMPDIR="$short_temp" + export TEMP="$short_temp" + export TMP="$short_temp" + + python - <<'PY' + import os + import tempfile + + print(f'Configured temporary directory: {os.environ["TEMP"]}') + print(f'Python temporary directory: {tempfile.gettempdir()}') + PY + + python -m pip install \ + "setuptools>=68" \ + wheel \ + "cmake>=3.15" \ + "pybind11>=3.0.1,<3.1" + rm -rf win7-wheels mkdir win7-wheels - python -m pip wheel \ - --no-cache-dir \ - --no-deps \ - --no-binary=Xray-core,hysteria2,tun2socks \ - --wheel-dir win7-wheels \ - "Xray-core==${XRAY_CORE_VERSION}" \ - "hysteria2==${HYSTERIA2_VERSION}" \ + bindings=( + "Xray-core==${XRAY_CORE_VERSION}" + "hysteria2==${HYSTERIA2_VERSION}" "tun2socks==${TUN2SOCKS_VERSION}" + ) + + for binding in "${bindings[@]}" + do + python -m pip wheel \ + --no-cache-dir \ + --no-build-isolation \ + --no-deps \ + --no-binary=:all: \ + --wheel-dir win7-wheels \ + "${binding}" + done python - <<'PY' from pathlib import Path @@ -371,26 +437,78 @@ jobs: "hysteria2==${HYSTERIA2_VERSION}" \ "tun2socks==${TUN2SOCKS_VERSION}" if: matrix.id != 'windows-win7-amd64' - - name: Verify Windows binding architecture and imports + - name: Verify Windows binding imports run: | - python VerifyWindowsArchitecture.py \ - --expected "${{ matrix.windows-architecture }}" \ - --bindings + python - <<'PY' + import importlib + + for name in ('xray', 'hysteria', 'hysteria2', 'tun2socks'): + module = importlib.import_module(name) + print(f'{name}: {module.__file__}') + + # Native extension imports fail here if a wheel has the wrong machine type. + print('All native bindings imported successfully') + PY if: runner.os == 'Windows' - name: Download latest asset files run: | python Deploy.py --download - name: Run deploy script + env: + APPIMAGE_EXTRACT_AND_RUN: "1" run: | if [[ -n "${{ matrix.windows-compatibility }}" ]]; then export WIN_VER_COMPATIBLE="${{ matrix.windows-compatibility }}" fi python Deploy.py - name: Verify packaged Windows binaries + env: + EXPECTED_WINDOWS_ARCHITECTURE: ${{ matrix.windows-architecture }} run: | - python VerifyWindowsArchitecture.py \ - --expected "${{ matrix.windows-architecture }}" \ - --tree "Furious-Deploy/Furious.dist" + python - <<'PY' + import os + import struct + from pathlib import Path + + machineCodes = { + 'amd64': 0x8664, + 'arm64': 0xAA64, + } + expected = os.environ['EXPECTED_WINDOWS_ARCHITECTURE'] + expectedMachine = machineCodes[expected] + root = Path('Furious-Deploy/Furious.dist') + binaries = sorted( + { + *root.rglob('*.exe'), + *root.rglob('*.pyd'), + } + ) + + if not binaries: + raise SystemExit(f'no packaged Windows binaries found below {root}') + + for binary in binaries: + with binary.open('rb') as stream: + if stream.read(2) != b'MZ': + raise SystemExit(f'{binary} is not a PE binary') + + stream.seek(0x3C) + peOffset = struct.unpack('