name: Release 3X-UI on: workflow_dispatch: release: types: [published] push: branches: - main paths: - '.github/workflows/release.yml' - '**.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@v4 - name: Setup Go uses: actions/setup-go@v5 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.8.3/" 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' 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 prerelease: true