diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index af9134d..799d541 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -16,22 +16,92 @@ on: - 'windows/**' jobs: - build-windows: - strategy: - matrix: - platform: - - amd64 - - arm64 - include: - - platform: amd64 - goarch: amd64 - suffix: "" - - platform: arm64 - goarch: arm64 - suffix: "-arm64" - + build-windows: + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@v5.0.0 + with: + submodules: recursive + fetch-depth: 0 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + cache: false + go-version-file: go.mod + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + registry-url: 'https://registry.npmjs.org' + + - name: Install zip for Windows + shell: powershell + run: | + # Install Chocolatey if not available + if (!(Get-Command choco -ErrorAction SilentlyContinue)) { + Set-ExecutionPolicy Bypass -Scope Process -Force + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + } + # Install zip + choco install zip -y + + - name: Build frontend + shell: bash + run: | + cd frontend + npm install + npm run build + cd .. + mv frontend/dist web/html + rm -fr frontend + + - name: Build s-ui + shell: bash + run: | + export CGO_ENABLED=1 + export GOOS=windows + export GOARCH=amd64 + + echo "Building for Windows amd64" + go version + + ### Build s-ui + go build -ldflags="-w -s" -tags "with_quic,with_grpc,with_utls,with_acme,with_gvisor" -o sui.exe main.go + file sui.exe + + mkdir s-ui-windows + cp sui.exe s-ui-windows/ + cp -r windows/* s-ui-windows/ + + - name: Package + shell: bash + run: | + zip -r "s-ui-windows-amd64.zip" s-ui-windows + + - name: Upload files to Artifacts + uses: actions/upload-artifact@v4 + with: + name: s-ui-windows-amd64 + path: ./s-ui-windows-amd64.zip + retention-days: 30 + + - name: Upload to Release + uses: svenstaro/upload-release-action@v2 + if: github.event_name == 'release' && github.event.action == 'published' + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ github.ref }} + file: s-ui-windows-amd64.zip + asset_name: s-ui-windows-amd64.zip + prerelease: true + overwrite: true + + build-windows-arm64: runs-on: ubuntu-latest - steps: - name: Checkout repository uses: actions/checkout@v5.0.0 @@ -60,50 +130,42 @@ jobs: mv frontend/dist web/html rm -fr frontend - - name: Build S-UI for Windows + - name: Build s-ui for ARM64 run: | - export CGO_ENABLED=1 + export CGO_ENABLED=0 export GOOS=windows - export GOARCH=${{ matrix.goarch }} + export GOARCH=arm64 - # Install MinGW-w64 for Windows cross-compilation - sudo apt-get update - sudo apt-get install -y mingw-w64 + echo "Building for Windows ARM64 (32-bit)" + go version + go env GOOS GOARCH - # Set CC based on architecture - case "${{ matrix.goarch }}" in - amd64) export CC=x86_64-w64-mingw32-gcc ;; - arm64) export CC=x86_64-w64-mingw32-gcc ;; # MinGW doesn't support ARM64 well, use x86_64 - esac - - echo "Using CC: $CC" - echo "GOOS: $GOOS, GOARCH: $GOARCH" - - ### Build s-ui for Windows - go build -ldflags="-w -s" -tags "with_quic,with_grpc,with_utls,with_acme,with_gvisor" -o "sui${{ matrix.suffix }}.exe" main.go - file "sui${{ matrix.suffix }}.exe" + ### Build s-ui without CGO for ARM64 + go build -ldflags="-w -s" -tags "with_quic,with_grpc,with_utls,with_acme,with_gvisor" -o sui.exe main.go + file sui.exe mkdir s-ui-windows - cp "sui${{ matrix.suffix }}.exe" s-ui-windows/sui.exe + cp sui.exe s-ui-windows/ cp -r windows/* s-ui-windows/ - - name: Package - run: zip -r "s-ui-windows-${{ matrix.platform }}.zip" s-ui-windows + - name: Package ARM64 + run: | + zip -r "s-ui-windows-arm64.zip" s-ui-windows - - name: Upload files to Artifacts + - name: Upload ARM64 files to Artifacts uses: actions/upload-artifact@v4 with: - name: s-ui-windows-${{ matrix.platform }} - path: ./s-ui-windows-${{ matrix.platform }}.zip + name: s-ui-windows-arm64 + path: ./s-ui-windows-arm64.zip retention-days: 30 - - name: Upload to Release + - name: Upload ARM64 to Release uses: svenstaro/upload-release-action@v2 if: github.event_name == 'release' && github.event.action == 'published' with: repo_token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ github.ref }} - file: s-ui-windows-${{ matrix.platform }}.zip - asset_name: s-ui-windows-${{ matrix.platform }}.zip + file: s-ui-windows-arm64.zip + asset_name: s-ui-windows-arm64.zip prerelease: true overwrite: true diff --git a/database/backup.go b/database/backup.go index 9ca3bd4..612f63c 100644 --- a/database/backup.go +++ b/database/backup.go @@ -7,6 +7,7 @@ import ( "mime/multipart" "os" "path/filepath" + "runtime" "s-ui/cmd/migration" "s-ui/config" "s-ui/database/model" @@ -287,7 +288,11 @@ func SendSighup() error { // Send SIGHUP to the current process go func() { time.Sleep(3 * time.Second) - err := process.Signal(syscall.SIGHUP) + if runtime.GOOS == "windows" { + err = process.Kill() + } else { + err = process.Signal(syscall.SIGHUP) + } if err != nil { logger.Error("send signal SIGHUP failed:", err) } diff --git a/service/panel.go b/service/panel.go index 4d85dc5..e8e8ef6 100644 --- a/service/panel.go +++ b/service/panel.go @@ -2,6 +2,7 @@ package service import ( "os" + "runtime" "s-ui/logger" "syscall" "time" @@ -17,7 +18,11 @@ func (s *PanelService) RestartPanel(delay time.Duration) error { } go func() { time.Sleep(delay) - err := p.Signal(syscall.SIGHUP) + if runtime.GOOS == "windows" { + err = p.Kill() + } else { + err = p.Signal(syscall.SIGHUP) + } if err != nil { logger.Error("send signal SIGHUP failed:", err) } diff --git a/service/setting.go b/service/setting.go index 8735716..581c6cb 100644 --- a/service/setting.go +++ b/service/setting.go @@ -3,6 +3,7 @@ package service import ( "encoding/json" "os" + "runtime" "s-ui/config" "s-ui/database" "s-ui/database/model" @@ -245,6 +246,9 @@ func (s *SettingService) GetTimeLocation() (*time.Location, error) { if err != nil { return nil, err } + if runtime.GOOS == "windows" { + l = "Local" + } location, err := time.LoadLocation(l) if err != nil { defaultLocation := defaultValueMap["timeLocation"] diff --git a/windows/install-windows.bat b/windows/install-windows.bat index 5cce6d3..565c829 100644 --- a/windows/install-windows.bat +++ b/windows/install-windows.bat @@ -36,7 +36,7 @@ REM Check if WinSW is available set "WINSW_PATH=%INSTALL_DIR%\winsw.exe" if not exist "%WINSW_PATH%" ( echo Downloading WinSW... - powershell -Command "& {Invoke-WebRequest -Uri 'https://github.com/winsw/winsw/releases/download/v3.0.0/WinSW-x64.exe' -OutFile '%WINSW_PATH%'}" + powershell -Command "& {Invoke-WebRequest -Uri 'https://github.com/winsw/winsw/releases/download/v2.12.0/WinSW-x64.exe' -OutFile '%WINSW_PATH%'}" if exist "%WINSW_PATH%" ( echo WinSW downloaded successfully ) else ( @@ -51,10 +51,7 @@ if exist "%WINSW_PATH%" ( cd /d "%INSTALL_DIR%" copy "winsw.exe" "s-ui-service.exe" >nul copy "s-ui-windows.xml" "s-ui-service.xml" >nul - - REM Update XML with correct paths - powershell -Command "& {(Get-Content 's-ui-service.xml') -replace '%BASE%', '%INSTALL_DIR%' | Set-Content 's-ui-service.xml'}" - + REM Install service s-ui-service.exe install if %errorLevel% equ 0 (