| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 | name: Release 3X-UIon:  workflow_dispatch:  release:    types: [published]  push:    branches:      - main    tags:      - "v*.*.*"    paths:      - '**.js'      - '**.css'      - '**.html'      - '**.sh'      - '**.go'      - 'go.mod'      - 'go.sum'      - 'x-ui.service'jobs:  build:    permissions:      contents: write    strategy:      matrix:        platform:          - amd64          - arm64          - armv7          - armv6          - 386          - armv5          - s390x    runs-on: ubuntu-latest    steps:      - name: Checkout repository        uses: actions/checkout@v5      - name: Setup Go        uses: actions/setup-go@v6        with:          go-version-file: go.mod          check-latest: true      - name: Build 3X-UI        run: |          export CGO_ENABLED=1          export GOOS=linux          export GOARCH=${{ matrix.platform }}          # Use Bootlin prebuilt cross-toolchains (musl 1.2.5 in stable series)          case "${{ matrix.platform }}" in            amd64) BOOTLIN_ARCH="x86-64" ;;            arm64) BOOTLIN_ARCH="aarch64" ;;            armv7) BOOTLIN_ARCH="armv7-eabihf"; export GOARCH=arm GOARM=7 ;;            armv6) BOOTLIN_ARCH="armv6-eabihf"; export GOARCH=arm GOARM=6 ;;            armv5) BOOTLIN_ARCH="armv5-eabi"; export GOARCH=arm GOARM=5 ;;            386) BOOTLIN_ARCH="x86-i686" ;;            s390x) BOOTLIN_ARCH="s390x-z13" ;;          esac          echo "Resolving Bootlin musl toolchain for arch=$BOOTLIN_ARCH (platform=${{ matrix.platform }})"          TARBALL_BASE="https://toolchains.bootlin.com/downloads/releases/toolchains/$BOOTLIN_ARCH/tarballs/"          TARBALL_URL=$(curl -fsSL "$TARBALL_BASE" | grep -oE "${BOOTLIN_ARCH}--musl--stable-[^\"]+\\.tar\\.xz" | sort -r | head -n1)          [ -z "$TARBALL_URL" ] && { echo "Failed to locate Bootlin musl toolchain for arch=$BOOTLIN_ARCH" >&2; exit 1; }          echo "Downloading: $TARBALL_URL"          cd /tmp          curl -fL -sS -o "$(basename "$TARBALL_URL")" "$TARBALL_BASE/$TARBALL_URL"          tar -xf "$(basename "$TARBALL_URL")"          TOOLCHAIN_DIR=$(find . -maxdepth 1 -type d -name "${BOOTLIN_ARCH}--musl--stable-*" | head -n1)          export PATH="$(realpath "$TOOLCHAIN_DIR")/bin:$PATH"          export CC=$(realpath "$(find "$TOOLCHAIN_DIR/bin" -name '*-gcc.br_real' -type f -executable | head -n1)")          [ -z "$CC" ] && { echo "No gcc.br_real found in $TOOLCHAIN_DIR/bin" >&2; exit 1; }          cd -          go build -ldflags "-w -s -linkmode external -extldflags '-static'" -o xui-release -v main.go          file xui-release          ldd xui-release || echo "Static binary confirmed"                    mkdir x-ui          cp xui-release x-ui/          cp x-ui.service x-ui/          cp x-ui.sh x-ui/          mv x-ui/xui-release x-ui/x-ui          mkdir x-ui/bin          cd x-ui/bin                    # Download dependencies          Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v25.10.15/"          if [ "${{ matrix.platform }}" == "amd64" ]; then            wget -q ${Xray_URL}Xray-linux-64.zip            unzip Xray-linux-64.zip            rm -f Xray-linux-64.zip          elif [ "${{ matrix.platform }}" == "arm64" ]; then            wget -q ${Xray_URL}Xray-linux-arm64-v8a.zip            unzip Xray-linux-arm64-v8a.zip            rm -f Xray-linux-arm64-v8a.zip          elif [ "${{ matrix.platform }}" == "armv7" ]; then            wget -q ${Xray_URL}Xray-linux-arm32-v7a.zip            unzip Xray-linux-arm32-v7a.zip            rm -f Xray-linux-arm32-v7a.zip          elif [ "${{ matrix.platform }}" == "armv6" ]; then            wget -q ${Xray_URL}Xray-linux-arm32-v6.zip            unzip Xray-linux-arm32-v6.zip            rm -f Xray-linux-arm32-v6.zip          elif [ "${{ matrix.platform }}" == "386" ]; then            wget -q ${Xray_URL}Xray-linux-32.zip            unzip Xray-linux-32.zip            rm -f Xray-linux-32.zip          elif [ "${{ matrix.platform }}" == "armv5" ]; then            wget -q ${Xray_URL}Xray-linux-arm32-v5.zip            unzip Xray-linux-arm32-v5.zip            rm -f Xray-linux-arm32-v5.zip          elif [ "${{ matrix.platform }}" == "s390x" ]; then            wget -q ${Xray_URL}Xray-linux-s390x.zip            unzip Xray-linux-s390x.zip            rm -f Xray-linux-s390x.zip          fi          rm -f geoip.dat geosite.dat          wget -q https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat          wget -q https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat          wget -q -O geoip_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat          wget -q -O geosite_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat          wget -q -O geoip_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat          wget -q -O geosite_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat          mv xray xray-linux-${{ matrix.platform }}          cd ../..                - name: Package        run: tar -zcvf x-ui-linux-${{ matrix.platform }}.tar.gz x-ui      - name: Upload files to Artifacts        uses: actions/upload-artifact@v4        with:          name: x-ui-linux-${{ matrix.platform }}          path: ./x-ui-linux-${{ matrix.platform }}.tar.gz      - name: Upload files to GH release        uses: svenstaro/upload-release-action@v2        if: |          (github.event_name == 'release' && github.event.action == 'published') ||          (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))        with:          repo_token: ${{ secrets.GITHUB_TOKEN }}          tag: ${{ github.ref }}          file: x-ui-linux-${{ matrix.platform }}.tar.gz          asset_name: x-ui-linux-${{ matrix.platform }}.tar.gz          overwrite: true          prerelease: true  # =================================  #  Windows Build  # =================================  build-windows:    name: Build for Windows    permissions:      contents: write    strategy:      matrix:        platform:          - amd64    runs-on: windows-latest    steps:      - name: Checkout repository        uses: actions/checkout@v5      - name: Setup Go        uses: actions/setup-go@v6        with:          go-version-file: go.mod          check-latest: true      - name: Build 3X-UI for Windows        shell: pwsh        run: |          $env:CGO_ENABLED="1"          $env:GOOS="windows"          $env:GOARCH="amd64"          go build -ldflags "-w -s" -o xui-release.exe -v main.go                    mkdir x-ui          Copy-Item xui-release.exe x-ui\          mkdir x-ui\bin          cd x-ui\bin                    # Download Xray for Windows          $Xray_URL = "https://github.com/XTLS/Xray-core/releases/download/v25.10.15/"          Invoke-WebRequest -Uri "${Xray_URL}Xray-windows-64.zip" -OutFile "Xray-windows-64.zip"          Expand-Archive -Path "Xray-windows-64.zip" -DestinationPath .          Remove-Item "Xray-windows-64.zip"          Remove-Item geoip.dat, geosite.dat -ErrorAction SilentlyContinue          Invoke-WebRequest -Uri "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat" -OutFile "geoip.dat"          Invoke-WebRequest -Uri "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat" -OutFile "geosite.dat"          Invoke-WebRequest -Uri "https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat" -OutFile "geoip_IR.dat"          Invoke-WebRequest -Uri "https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat" -OutFile "geosite_IR.dat"          Invoke-WebRequest -Uri "https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat" -OutFile "geoip_RU.dat"          Invoke-WebRequest -Uri "https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat" -OutFile "geosite_RU.dat"          Rename-Item xray.exe xray-windows-amd64.exe          cd ..          Copy-Item -Path ..\windows_files\* -Destination . -Recurse          cd ..      - name: Package to Zip        shell: pwsh        run: |          Compress-Archive -Path .\x-ui -DestinationPath "x-ui-windows-amd64.zip"      - name: Upload files to Artifacts        uses: actions/upload-artifact@v4        with:          name: x-ui-windows-amd64          path: ./x-ui-windows-amd64.zip      - name: Upload files to GH release        uses: svenstaro/upload-release-action@v2        if: |          (github.event_name == 'release' && github.event.action == 'published') ||          (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))        with:          repo_token: ${{ secrets.GITHUB_TOKEN }}          tag: ${{ github.ref }}          file: x-ui-windows-amd64.zip          asset_name: x-ui-windows-amd64.zip          overwrite: true          prerelease: true
 |