Update workflow

Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Loren Eteval
2026-08-23 16:41:07 +08:00
parent f8f70bf7ab
commit 38375bcce0
3 changed files with 265 additions and 105 deletions
+235 -79
View File
@@ -78,33 +78,63 @@ jobs:
uses: pypa/gh-action-pypi-publish@release/v1
deploy-binaries:
name: Deploy binaries on ${{ matrix.os }} Python ${{ matrix.python-version }}
name: Deploy ${{ matrix.id }} on ${{ matrix.os }} Python ${{ matrix.python-version }}
runs-on: ${{ matrix.os }}
continue-on-error: true
strategy:
fail-fast: false
matrix:
os: [ ubuntu-22.04, ubuntu-22.04-arm, windows-2025, macos-15-intel, macos-14 ]
python-version: [ "3.11", "3.13" ]
exclude:
- os: ubuntu-22.04
python-version: "3.11"
- os: windows-2025
python-version: "3.11"
- os: macos-15-intel
python-version: "3.11"
- os: macos-14
python-version: "3.11"
- os: ubuntu-22.04-arm
python-version: "3.13"
include:
- os: windows-2025
id: win7
- id: linux-amd64
os: ubuntu-22.04
python-version: "3.13"
python-architecture: x64
pyside6-version: "6.8.3"
windows-compatibility: ""
windows-architecture: ""
- id: linux-arm64
os: ubuntu-22.04-arm
python-version: "3.11"
python-architecture: arm64
pyside6-version: "6.5.3"
windows-compatibility: ""
windows-architecture: ""
- id: windows-win7-amd64
os: windows-2025
python-version: "3.13"
python-architecture: x64
pyside6-version: "6.8.3"
windows-compatibility: windows
windows-architecture: amd64
- id: windows-arm64
os: windows-11-vs2026-arm
python-version: "3.13"
python-architecture: arm64
pyside6-version: "6.11.2"
windows-compatibility: ""
windows-architecture: arm64
- id: macos-intel
os: macos-15-intel
python-version: "3.13"
python-architecture: x64
pyside6-version: "6.8.3"
windows-compatibility: ""
windows-architecture: ""
- id: macos-arm64
os: macos-14
python-version: "3.13"
python-architecture: arm64
pyside6-version: "6.8.3"
windows-compatibility: ""
windows-architecture: ""
env:
# Last PySide6 version that supports macOS 10.9 & Python 3.11
PYSIDE6_LEGACY_VERSION: "6.4.3"
PYSIDE6_TARGET_VERSION: "6.8.3"
# PySide6 has Windows ARM64 build since 6.9.0
PYSIDE6_LATEST_VERSION: "6.9.1"
XRAY_CORE_VERSION: "1.8.26.9"
HYSTERIA_VERSION: "1.3.5.4"
HYSTERIA2_VERSION: "2.12.1.1"
TUN2SOCKS_VERSION: "2.7.0.1"
GO_WIN7_VERSION: "1.26.7"
NUITKA_VERSION: "4.1.3"
WIX_VERSION: "6.0.2"
steps:
- uses: actions/checkout@v7
- name: Install macOS dependencies
@@ -149,97 +179,223 @@ jobs:
if: runner.os == 'Linux'
- name: Install Windows dependencies
run: |
if [ "$RUNNER_ARCH" == "X64" ]; then
toolset_arch="x64"
elif [ "$RUNNER_ARCH" == "ARM64" ]; then
toolset_arch="arm64"
else
echo "Unknown runner architecture: $RUNNER_ARCH"
exit 1
fi
winget install --id WiXToolset.WiXCLI --version 6.0.2.0 -e --source winget --accept-package-agreements --accept-source-agreements
echo "C:/Program Files/WiX Toolset v6.0/bin" >> $GITHUB_PATH
echo "C:/Program Files/WiX Toolset v6.0/bin/${toolset_arch}" >> $GITHUB_PATH
dotnet tool install --global wix --version "${WIX_VERSION}"
echo "$HOME/.dotnet/tools" >> $GITHUB_PATH
if: runner.os == 'Windows'
- name: Check Windows dependencies
run: |
wix --version
wix extension add WixToolset.UI.wixext/6.0.2
wix extension add "WixToolset.UI.wixext/${WIX_VERSION}"
if: runner.os == 'Windows'
- name: Set up Python for Windows7
uses: LorenEteval/setup-python-win7@v1
with:
python-version: ${{ matrix.python-version }}
check-latest: true
if: matrix.id == 'win7'
if: matrix.id == 'windows-win7-amd64'
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.python-architecture }}
check-latest: true
if: matrix.id != 'win7'
if: matrix.id != 'windows-win7-amd64'
- name: Verify runner and Python architecture
env:
EXPECTED_ARCHITECTURE: ${{ matrix.python-architecture }}
run: |
python - <<'PY'
import os
import platform
import struct
import sys
aliases = {
'x64': {'amd64', 'x86_64'},
'arm64': {'arm64', 'aarch64'},
}
expected = os.environ['EXPECTED_ARCHITECTURE']
runner_architecture = os.environ.get('RUNNER_ARCH', '').casefold()
machine = platform.machine().casefold()
pointer_width = struct.calcsize('P') * 8
print(f'RUNNER_OS={os.environ.get("RUNNER_OS")}')
print(f'RUNNER_ARCH={os.environ.get("RUNNER_ARCH")}')
print(f'Python={sys.version}')
print(f'platform.machine()={platform.machine()}')
print(f'pointer width={pointer_width}')
if runner_architecture != expected:
raise SystemExit(
f'expected {expected} runner, got {runner_architecture or "unknown"}'
)
if machine not in aliases[expected] or pointer_width != 64:
raise SystemExit(
f'expected native {expected} Python, got {machine}/{pointer_width}-bit'
)
PY
- name: Set up PySide6 for Windows7
uses: LorenEteval/setup-pyside6-win7@v1
with:
pyside6-version: ${{ env.PYSIDE6_TARGET_VERSION }}
if: matrix.id == 'win7'
- name: Download Python dependencies & latest asset files
pyside6-version: ${{ matrix.pyside6-version }}
if: matrix.id == 'windows-win7-amd64'
- name: Install Python build and runtime dependencies
run: |
python -c "import sys; print(sys.version)"
python -m pip install --upgrade pip
python -m pip install setuptools wheel
python - <<'PY'
from pathlib import Path
import re
excluded = {
'pyside6-addons',
'pyside6-essentials',
'xray-core',
'hysteria',
'hysteria2',
'tun2socks',
}
requirements = []
for line in Path('requirements.txt').read_text(encoding='utf-8').splitlines():
match = re.match(r'\s*([A-Za-z0-9_.-]+)', line)
if match and match.group(1).casefold().replace('_', '-') in excluded:
continue
requirements.append(line)
Path('.binary-requirements.txt').write_text(
'\n'.join(requirements) + '\n',
encoding='utf-8',
)
PY
if [[ "${{ matrix.id }}" != "windows-win7-amd64" ]]; then
if [[ "$RUNNER_OS" == "Windows" ]]; then
pyside_binary_policy="--only-binary=PySide6-Essentials,PySide6-Addons"
else
pyside_binary_policy=""
fi
python -m pip install \
${pyside_binary_policy} \
"PySide6-Essentials==${{ matrix.pyside6-version }}" \
"PySide6-Addons==${{ matrix.pyside6-version }}"
fi
if [ "$RUNNER_OS" == "Linux" ] && [ "$RUNNER_ARCH" == "ARM64" ]; then
python -m pip install "numpy<2"
python -m pip install PySide6-Essentials==6.5.3
fi
python -m pip install -r .binary-requirements.txt
python -m pip install "Nuitka==${NUITKA_VERSION}" imageio requests
python -c "from PySide6 import QtCore; print(f'PySide6/Qt {QtCore.__version__}')"
- name: Install patched Go for Windows7
run: |
go_name="go-for-win7-windows-amd64"
go_file="${go_name}.zip"
curl --fail --location --output "${go_file}" \
"https://github.com/XTLS/go-win7/releases/download/patched-${GO_WIN7_VERSION}/${go_file}"
7z x "${go_file}" "-o${go_name}" -y
go_root="$(cygpath -w "$PWD/${go_name}")"
echo "GOROOT=${go_root}" >> $GITHUB_ENV
echo "CGO_ENABLED=1" >> $GITHUB_ENV
echo "${go_root}\\bin" >> $GITHUB_PATH
if: matrix.id == 'windows-win7-amd64'
- name: Build Windows7 bindings from source with patched Go
run: |
command -v go
go version
go env GOROOT GOOS GOARCH CGO_ENABLED
command -v gcc
gcc -dumpmachine
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}" \
"tun2socks==${TUN2SOCKS_VERSION}"
python - <<'PY'
from pathlib import Path
wheels = sorted(Path('win7-wheels').glob('*.whl'))
print('Locally built wheels:')
for wheel in wheels:
print(f' {wheel.name}')
if len(wheels) != 3 or any('win_amd64.whl' not in wheel.name for wheel in wheels):
raise SystemExit('expected exactly three locally built win_amd64 wheels')
PY
python -m pip install \
--no-index \
--force-reinstall \
--no-deps \
win7-wheels/*.whl
if: matrix.id == 'windows-win7-amd64'
- name: Install Windows7-compatible Hysteria1 wheel
run: |
python -m pip install \
--only-binary=hysteria \
--no-cache-dir \
--no-deps \
"hysteria==${HYSTERIA_VERSION}"
if: matrix.id == 'windows-win7-amd64'
- name: Install supported binding wheels
run: |
if [[ "$RUNNER_OS" == "Windows" ]]; then
binary_policy="--only-binary=Xray-core,hysteria,hysteria2,tun2socks"
else
python -m pip install PySide6-Essentials==${PYSIDE6_TARGET_VERSION}
binary_policy=""
fi
python -m pip install -r requirements.txt
python -m pip install nuitka imageio requests
python -m pip install \
${binary_policy} \
--no-cache-dir \
--no-deps \
"Xray-core==${XRAY_CORE_VERSION}" \
"hysteria==${HYSTERIA_VERSION}" \
"hysteria2==${HYSTERIA2_VERSION}" \
"tun2socks==${TUN2SOCKS_VERSION}"
if: matrix.id != 'windows-win7-amd64'
- name: Verify Windows binding architecture and imports
run: |
python VerifyWindowsArchitecture.py \
--expected "${{ matrix.windows-architecture }}" \
--bindings
if: runner.os == 'Windows'
- name: Download latest asset files
run: |
python Deploy.py --download
- name: Set up go
uses: actions/setup-go@v7
with:
go-version: "1.26"
check-latest: true
if: matrix.id != 'win7'
- name: Install go dependencies
run: |
if [[ "${{ matrix.id }}" == "win7" ]]; then
go_name="go-for-win7-windows-amd64"
go_file="${go_name}.zip"
curl -L -o ${go_file} https://github.com/XTLS/go-win7/releases/download/patched-1.26.7/${go_file}
7z x ${go_file} -o${go_name} -y
export GOROOT="$PWD/${go_name}"
export CGO_ENABLED=1
export PATH="${GOROOT}/bin:$PATH"
fi
go version
python -m pip install "Xray-core >= 1.8.8"
python -m pip install "hysteria2 >= 2.0.4"
python -m pip install "tun2socks > 2.5.2"
- name: Set up go legacy
uses: actions/setup-go@v7
with:
go-version: "1.20"
check-latest: true
- name: Install go legacy dependencies
run: |
go version
python -m pip install "hysteria > 1.3.5"
- name: Run deploy script
run: |
if [[ "${{ matrix.id }}" == "win7" ]]; then
export WIN_VER_COMPATIBLE="windows"
if [[ -n "${{ matrix.windows-compatibility }}" ]]; then
export WIN_VER_COMPATIBLE="${{ matrix.windows-compatibility }}"
fi
python Deploy.py
- name: Verify packaged Windows binaries
run: |
python VerifyWindowsArchitecture.py \
--expected "${{ matrix.windows-architecture }}" \
--tree "Furious-Deploy/Furious.dist"
if: runner.os == 'Windows'
- name: Store the distribution packages
uses: actions/upload-artifact@v7
with:
name: binary-distributions-${{ matrix.os }}-Python${{ matrix.python-version }}
name: binary-distributions-${{ matrix.id }}-Python${{ matrix.python-version }}
path: |
Furious-*.zip
Furious-*.msi
@@ -294,6 +450,6 @@ jobs:
with:
identifier: LorenEteval.Furious
release-tag: ${{ github.ref_name }}
installers-regex: '^Furious-.*\.zip$'
installers-regex: '^Furious-.*-(?:windows-amd64|windows11-arm64)\.zip$'
max-versions-to-keep: 5
token: ${{ secrets.WINGET_TOKEN }}