Skip to content

Update gui.py

Update gui.py #108

Workflow file for this run

name: Build and Release
on:
push:
branches:
- main
- master
tags:
- 'v*'
pull_request:
branches:
- main
- master
workflow_dispatch:
jobs:
build:
strategy:
matrix:
include:
- os: windows-latest
goos: windows
goarch: amd64
exe_ext: .exe
archive_format: zip
archive_ext: .zip
target: desktop
artifact_suffix: ""
enable_gui: true
cgo_enabled: "0"
- os: macos-15-intel
goos: darwin
goarch: amd64
exe_ext: ""
archive_format: zip
archive_ext: .zip
target: desktop
artifact_suffix: ""
enable_gui: true
cgo_enabled: "0"
- os: macos-14
goos: darwin
goarch: arm64
exe_ext: ""
archive_format: zip
archive_ext: .zip
target: desktop
artifact_suffix: ""
enable_gui: true
cgo_enabled: "0"
- os: ubuntu-latest
goos: linux
goarch: amd64
exe_ext: ""
archive_format: tar.gz
archive_ext: .tar.gz
target: desktop
artifact_suffix: ""
enable_gui: true
cgo_enabled: "0"
- os: ubuntu-24.04-arm
goos: linux
goarch: arm64
exe_ext: ""
archive_format: tar.gz
archive_ext: .tar.gz
target: desktop
artifact_suffix: ""
enable_gui: true
cgo_enabled: "0"
- os: ubuntu-latest
goos: linux
goarch: amd64
exe_ext: ""
archive_format: tar.gz
archive_ext: .tar.gz
target: softrouter
artifact_suffix: "-softrouter"
enable_gui: false
cgo_enabled: "0"
- os: ubuntu-latest
goos: linux
goarch: arm64
exe_ext: ""
archive_format: tar.gz
archive_ext: .tar.gz
target: softrouter
artifact_suffix: "-softrouter"
enable_gui: false
cgo_enabled: "0"
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: false
- name: Initialize Go module
run: |
go mod init ech-workers || true
go mod tidy
- name: Build Go executable
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: ${{ matrix.cgo_enabled }}
run: |
echo "Building for $GOOS/$GOARCH (target=${{ matrix.target }}, CGO_ENABLED=$CGO_ENABLED)"
go build -trimpath -ldflags="-s -w" -o ech-workers${{ matrix.exe_ext }} ech-workers.go
shell: bash
# 下面这些步骤:只有打 tag 且 enable_gui == true 时才会执行,用来打包 GUI
- name: Set up Python
if: startsWith(github.ref, 'refs/tags/') && matrix.enable_gui == true
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install system dependencies (Linux)
if: startsWith(github.ref, 'refs/tags/') && matrix.goos == 'linux' && matrix.enable_gui == true
run: |
sudo apt-get update
sudo apt-get install -y python3-pyqt5 python3-pyqt5.qtsvg python3-dev
shell: bash
- name: Install PyInstaller, PySocks, and other dependencies
if: startsWith(github.ref, 'refs/tags/') && matrix.enable_gui == true
run: |
python -m pip install --upgrade pip
if [ "${{ matrix.goos }}" == "linux" ]; then
# Linux: 使用系统包中的 PyQt5,只安装其他依赖
pip install pyinstaller pystray Pillow PySocks
python -c "import PyQt5.QtWidgets; print('PyQt5 available')" || echo "PyQt5 not available, will skip GUI build"
else
# Windows / macOS: 从 PyPI 安装
pip install pyinstaller PyQt5 pystray Pillow PySocks
fi
shell: bash
- name: Check application icon
if: startsWith(github.ref, 'refs/tags/') && matrix.enable_gui == true
run: |
# 检查图标文件是否存在(图标文件已包含在仓库中)
echo "Checking for icon files..."
ls -lh app_icon.* 2>/dev/null || echo "No icon files found"
if [ "${{ matrix.goos }}" == "windows" ]; then
if [ -f "app_icon.ico" ]; then
echo "✓ Found app_icon.ico"
elif [ -f "app_icon.png" ]; then
echo "✓ Found app_icon.png (will be used as icon)"
else
echo "⚠ No icon file found, PyInstaller will use default icon"
fi
elif [ "${{ matrix.goos }}" == "darwin" ]; then
if [ -f "app_icon.icns" ]; then
echo "✓ Found app_icon.icns"
elif [ -f "app_icon.png" ]; then
echo "✓ Found app_icon.png (will be used as icon)"
else
echo "⚠ No icon file found, PyInstaller will use default icon"
fi
else
if [ -f "app_icon.png" ]; then
echo "✓ Found app_icon.png"
else
echo "⚠ No icon file found, PyInstaller will use default icon"
fi
fi
shell: bash
- name: Build Python executable
if: startsWith(github.ref, 'refs/tags/') && matrix.enable_gui == true
run: |
# 构建 PyInstaller 命令,根据平台添加图标
ICON_ARG=""
if [ "${{ matrix.goos }}" == "windows" ]; then
if [ -f "app_icon.ico" ]; then
ICON_ARG="--icon=app_icon.ico"
elif [ -f "app_icon.png" ]; then
ICON_ARG="--icon=app_icon.png"
fi
pyinstaller --onefile --windowed --name ECHWorkersGUI --hidden-import=PyQt5 $ICON_ARG gui.py
elif [ "${{ matrix.goos }}" == "linux" ]; then
if python -c "import PyQt5.QtWidgets" 2>/dev/null; then
if [ -f "app_icon.png" ]; then
ICON_ARG="--icon=app_icon.png"
fi
pyinstaller --onefile --name ECHWorkersGUI --hidden-import=PyQt5 $ICON_ARG gui.py
else
echo "PyQt5 not available, skipping GUI build for Linux"
echo "Only Go executable will be included"
fi
else
# macOS
if [ -f "app_icon.icns" ]; then
ICON_ARG="--icon=app_icon.icns"
elif [ -f "app_icon.png" ]; then
ICON_ARG="--icon=app_icon.png"
fi
pyinstaller --onefile --name ECHWorkersGUI --hidden-import=PyQt5 $ICON_ARG gui.py
fi
shell: bash
- name: Download China IP list
if: startsWith(github.ref, 'refs/tags/')
run: |
echo "Downloading latest China IP list (IPv4 and IPv6)..."
curl -L -o chn_ip.txt "https://raw.githubusercontent.com/mayaxcn/china-ip-list/refs/heads/master/chn_ip.txt" || echo "Failed to download IPv4 list, will skip"
curl -L -o chn_ip_v6.txt "https://raw.githubusercontent.com/mayaxcn/china-ip-list/refs/heads/master/chn_ip_v6.txt" || echo "Failed to download IPv6 list, will skip"
if [ -f "chn_ip.txt" ]; then
echo "✓ China IPv4 IP list downloaded successfully"
wc -l chn_ip.txt
else
echo "⚠ China IPv4 IP list download failed, release will continue without it"
fi
if [ -f "chn_ip_v6.txt" ]; then
echo "✓ China IPv6 IP list downloaded successfully"
wc -l chn_ip_v6.txt
else
echo "⚠ China IPv6 IP list download failed, release will continue without it"
fi
shell: bash
- name: Prepare release files
if: startsWith(github.ref, 'refs/tags/')
run: |
mkdir -p release
# Go 可执行文件
cp ech-workers${{ matrix.exe_ext }} release/
# 中国IP列表文件(离线版本)
if [ -f "chn_ip.txt" ]; then
cp chn_ip.txt release/
echo "✓ China IPv4 IP list included in release"
fi
if [ -f "chn_ip_v6.txt" ]; then
cp chn_ip_v6.txt release/
echo "✓ China IPv6 IP list included in release"
fi
# GUI(仅桌面版)
if [ "${{ matrix.enable_gui }}" = "true" ]; then
if [ "${{ matrix.goos }}" == "windows" ]; then
if [ -f "dist/ECHWorkersGUI.exe" ]; then
cp dist/ECHWorkersGUI.exe release/
fi
else
if [ -f "dist/ECHWorkersGUI" ]; then
cp dist/ECHWorkersGUI release/
chmod +x release/ECHWorkersGUI
elif [ "${{ matrix.goos }}" == "linux" ]; then
echo "GUI executable not built, only Go executable will be included"
fi
fi
fi
# README
{
echo "ECH Workers Client"
echo ""
echo "Target: ${{ matrix.target }}"
echo ""
echo "Files:"
echo "- ech-workers${{ matrix.exe_ext }}: Go compiled core proxy program"
if [ -f "release/chn_ip.txt" ]; then
echo "- chn_ip.txt: China IPv4 IP list (offline version)"
fi
if [ -f "release/chn_ip_v6.txt" ]; then
echo "- chn_ip_v6.txt: China IPv6 IP list (offline version)"
fi
if [ "${{ matrix.enable_gui }}" = "true" ]; then
if [ "${{ matrix.goos }}" == "windows" ]; then
echo "- ECHWorkersGUI.exe: Python GUI client (standalone executable)"
elif [ -f "release/ECHWorkersGUI" ]; then
echo "- ECHWorkersGUI: Python GUI client (standalone executable)"
else
echo "- Note: GUI client not available for this architecture"
echo " Use ech-workers from command line instead"
fi
else
echo "- GUI client not included for this build (CLI only, suitable for routers / servers)"
fi
echo ""
echo "Usage:"
if [ "${{ matrix.goos }}" == "windows" ]; then
echo "1. Double-click ECHWorkersGUI.exe to launch the GUI (if present)"
echo "2. Or run ech-workers.exe from command line"
else
echo "1. Run ./ech-workers from command line"
if [ "${{ matrix.enable_gui }}" = "true" ]; then
echo "2. Or run ./ECHWorkersGUI to launch the GUI"
fi
fi
echo ""
echo "System Requirements:"
if [ "${{ matrix.target }}" = "softrouter" ]; then
echo "- Linux soft router / NAS (OpenWrt / iStoreOS / x86_64 or ARM64)"
echo "- Architecture: ${{ matrix.goarch }}"
echo "- Recommended: run from SSH / shell"
else
if [ "${{ matrix.goos }}" == "windows" ]; then
echo "- Windows: Windows 10+"
elif [ "${{ matrix.goos }}" == "darwin" ]; then
echo "- macOS: macOS 10.13+"
else
echo "- Linux: Ubuntu 18.04+ / Debian 10+ / CentOS 7+"
echo "- Architecture: ${{ matrix.goarch }}"
fi
fi
echo "- No Python installation required for running the binaries"
} > release/README.txt
shell: bash
- name: Create archive (Windows)
if: startsWith(github.ref, 'refs/tags/') && matrix.goos == 'windows'
run: |
cd release
powershell Compress-Archive -Path * -DestinationPath ../ECHWorkers-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.artifact_suffix }}${{ matrix.archive_ext }} -Force
shell: powershell
- name: Create archive (macOS)
if: startsWith(github.ref, 'refs/tags/') && matrix.goos == 'darwin'
run: |
cd release
zip -r ../ECHWorkers-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.artifact_suffix }}${{ matrix.archive_ext }} .
shell: bash
- name: Create archive (Linux)
if: startsWith(github.ref, 'refs/tags/') && matrix.goos == 'linux'
run: |
cd release
tar -czf ../ECHWorkers-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.artifact_suffix }}${{ matrix.archive_ext }} .
shell: bash
- name: Upload artifacts
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-artifact@v4
with:
name: ECHWorkers-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.artifact_suffix }}
path: ECHWorkers-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.artifact_suffix }}${{ matrix.archive_ext }}
retention-days: 30
release:
needs: build
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create release
uses: softprops/action-gh-release@v1
with:
files: |
artifacts/**/*.zip
artifacts/**/*.tar.gz
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}