1
0

release.yml 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. name: Release 3X-UI
  2. on:
  3. workflow_dispatch:
  4. push:
  5. branches:
  6. - '**'
  7. tags:
  8. - "v*.*.*"
  9. paths:
  10. - '**.js'
  11. - '**.css'
  12. - '**.html'
  13. - '**.sh'
  14. - '**.go'
  15. - 'go.mod'
  16. - 'go.sum'
  17. - 'x-ui.service.debian'
  18. - 'x-ui.service.arch'
  19. - 'x-ui.service.rhel'
  20. pull_request:
  21. jobs:
  22. analyze:
  23. name: Analyze Go code
  24. permissions:
  25. contents: read
  26. runs-on: ubuntu-latest
  27. timeout-minutes: 20
  28. steps:
  29. - name: Checkout repository
  30. uses: actions/checkout@v6
  31. - name: Set up Go
  32. uses: actions/setup-go@v6
  33. with:
  34. go-version-file: go.mod
  35. cache: true
  36. - name: Check formatting
  37. run: |
  38. unformatted=$(gofmt -l .)
  39. if [ -n "$unformatted" ]; then
  40. echo "These files are not gofmt-formatted:"
  41. echo "$unformatted"
  42. exit 1
  43. fi
  44. - name: Run go vet
  45. run: go vet ./...
  46. - name: Run staticcheck
  47. uses: dominikh/staticcheck-action@v1
  48. with:
  49. version: "latest"
  50. install-go: false
  51. - name: Run tests
  52. run: go test -race -shuffle=on ./...
  53. build:
  54. needs: analyze
  55. permissions:
  56. contents: write
  57. strategy:
  58. matrix:
  59. platform:
  60. - amd64
  61. - arm64
  62. - armv7
  63. - armv6
  64. - 386
  65. - armv5
  66. - s390x
  67. runs-on: ubuntu-latest
  68. steps:
  69. - name: Checkout repository
  70. uses: actions/checkout@v6
  71. - name: Setup Go
  72. uses: actions/setup-go@v6
  73. with:
  74. go-version-file: go.mod
  75. check-latest: true
  76. - name: Build 3X-UI
  77. run: |
  78. export CGO_ENABLED=1
  79. export GOOS=linux
  80. export GOARCH=${{ matrix.platform }}
  81. # Use Bootlin prebuilt cross-toolchains (musl 1.2.5 in stable series)
  82. case "${{ matrix.platform }}" in
  83. amd64) BOOTLIN_ARCH="x86-64" ;;
  84. arm64) BOOTLIN_ARCH="aarch64" ;;
  85. armv7) BOOTLIN_ARCH="armv7-eabihf"; export GOARCH=arm GOARM=7 ;;
  86. armv6) BOOTLIN_ARCH="armv6-eabihf"; export GOARCH=arm GOARM=6 ;;
  87. armv5) BOOTLIN_ARCH="armv5-eabi"; export GOARCH=arm GOARM=5 ;;
  88. 386) BOOTLIN_ARCH="x86-i686" ;;
  89. s390x) BOOTLIN_ARCH="s390x-z13" ;;
  90. esac
  91. echo "Resolving Bootlin musl toolchain for arch=$BOOTLIN_ARCH (platform=${{ matrix.platform }})"
  92. TARBALL_BASE="https://toolchains.bootlin.com/downloads/releases/toolchains/$BOOTLIN_ARCH/tarballs/"
  93. TARBALL_URL=$(curl -fsSL "$TARBALL_BASE" | grep -oE "${BOOTLIN_ARCH}--musl--stable-[^\"]+\\.tar\\.xz" | sort -r | head -n1)
  94. [ -z "$TARBALL_URL" ] && { echo "Failed to locate Bootlin musl toolchain for arch=$BOOTLIN_ARCH" >&2; exit 1; }
  95. echo "Downloading: $TARBALL_URL"
  96. cd /tmp
  97. curl -fL -sS -o "$(basename "$TARBALL_URL")" "$TARBALL_BASE/$TARBALL_URL"
  98. tar -xf "$(basename "$TARBALL_URL")"
  99. TOOLCHAIN_DIR=$(find . -maxdepth 1 -type d -name "${BOOTLIN_ARCH}--musl--stable-*" | head -n1)
  100. export PATH="$(realpath "$TOOLCHAIN_DIR")/bin:$PATH"
  101. export CC=$(realpath "$(find "$TOOLCHAIN_DIR/bin" -name '*-gcc.br_real' -type f -executable | head -n1)")
  102. [ -z "$CC" ] && { echo "No gcc.br_real found in $TOOLCHAIN_DIR/bin" >&2; exit 1; }
  103. cd -
  104. go build -ldflags "-w -s -linkmode external -extldflags '-static'" -o xui-release -v main.go
  105. file xui-release
  106. ldd xui-release || echo "Static binary confirmed"
  107. mkdir x-ui
  108. cp xui-release x-ui/
  109. cp x-ui.service.debian x-ui/
  110. cp x-ui.service.arch x-ui/
  111. cp x-ui.service.rhel x-ui/
  112. cp x-ui.sh x-ui/
  113. mv x-ui/xui-release x-ui/x-ui
  114. mkdir x-ui/bin
  115. cd x-ui/bin
  116. # Download dependencies
  117. Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v26.2.6/"
  118. if [ "${{ matrix.platform }}" == "amd64" ]; then
  119. wget -q ${Xray_URL}Xray-linux-64.zip
  120. unzip Xray-linux-64.zip
  121. rm -f Xray-linux-64.zip
  122. elif [ "${{ matrix.platform }}" == "arm64" ]; then
  123. wget -q ${Xray_URL}Xray-linux-arm64-v8a.zip
  124. unzip Xray-linux-arm64-v8a.zip
  125. rm -f Xray-linux-arm64-v8a.zip
  126. elif [ "${{ matrix.platform }}" == "armv7" ]; then
  127. wget -q ${Xray_URL}Xray-linux-arm32-v7a.zip
  128. unzip Xray-linux-arm32-v7a.zip
  129. rm -f Xray-linux-arm32-v7a.zip
  130. elif [ "${{ matrix.platform }}" == "armv6" ]; then
  131. wget -q ${Xray_URL}Xray-linux-arm32-v6.zip
  132. unzip Xray-linux-arm32-v6.zip
  133. rm -f Xray-linux-arm32-v6.zip
  134. elif [ "${{ matrix.platform }}" == "386" ]; then
  135. wget -q ${Xray_URL}Xray-linux-32.zip
  136. unzip Xray-linux-32.zip
  137. rm -f Xray-linux-32.zip
  138. elif [ "${{ matrix.platform }}" == "armv5" ]; then
  139. wget -q ${Xray_URL}Xray-linux-arm32-v5.zip
  140. unzip Xray-linux-arm32-v5.zip
  141. rm -f Xray-linux-arm32-v5.zip
  142. elif [ "${{ matrix.platform }}" == "s390x" ]; then
  143. wget -q ${Xray_URL}Xray-linux-s390x.zip
  144. unzip Xray-linux-s390x.zip
  145. rm -f Xray-linux-s390x.zip
  146. fi
  147. rm -f geoip.dat geosite.dat
  148. wget -q https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
  149. wget -q https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat
  150. wget -q -O geoip_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat
  151. wget -q -O geosite_IR.dat https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat
  152. wget -q -O geoip_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat
  153. wget -q -O geosite_RU.dat https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat
  154. mv xray xray-linux-${{ matrix.platform }}
  155. cd ../..
  156. - name: Package
  157. run: tar -zcvf x-ui-linux-${{ matrix.platform }}.tar.gz x-ui
  158. - name: Upload files to Artifacts
  159. uses: actions/upload-artifact@v7
  160. with:
  161. name: x-ui-linux-${{ matrix.platform }}
  162. path: ./x-ui-linux-${{ matrix.platform }}.tar.gz
  163. - name: Upload files to GH release
  164. uses: svenstaro/upload-release-action@v2
  165. if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
  166. with:
  167. repo_token: ${{ secrets.GITHUB_TOKEN }}
  168. tag: ${{ github.ref_name }}
  169. file: x-ui-linux-${{ matrix.platform }}.tar.gz
  170. asset_name: x-ui-linux-${{ matrix.platform }}.tar.gz
  171. overwrite: true
  172. prerelease: true
  173. # =================================
  174. # Windows Build
  175. # =================================
  176. build-windows:
  177. name: Build for Windows
  178. needs: analyze
  179. permissions:
  180. contents: write
  181. strategy:
  182. matrix:
  183. platform:
  184. - amd64
  185. runs-on: windows-latest
  186. steps:
  187. - name: Checkout repository
  188. uses: actions/checkout@v6
  189. - name: Setup Go
  190. uses: actions/setup-go@v6
  191. with:
  192. go-version-file: go.mod
  193. check-latest: true
  194. - name: Install MSYS2
  195. uses: msys2/setup-msys2@v2
  196. with:
  197. msystem: MINGW64
  198. update: true
  199. install: >-
  200. mingw-w64-x86_64-gcc
  201. mingw-w64-x86_64-sqlite3
  202. mingw-w64-x86_64-pkg-config
  203. - name: Build 3X-UI for Windows (CGO)
  204. shell: msys2 {0}
  205. run: |
  206. export PATH="/c/hostedtoolcache/windows/go/$(ls /c/hostedtoolcache/windows/go | sort -V | tail -n1)/x64/bin:$PATH"
  207. export CGO_ENABLED=1
  208. export GOOS=windows
  209. export GOARCH=amd64
  210. export CC=x86_64-w64-mingw32-gcc
  211. which go
  212. go version
  213. gcc --version
  214. go build -ldflags "-w -s" -o xui-release.exe -v main.go
  215. - name: Copy and download resources
  216. shell: pwsh
  217. run: |
  218. mkdir x-ui
  219. Copy-Item xui-release.exe x-ui\x-ui.exe
  220. mkdir x-ui\bin
  221. cd x-ui\bin
  222. # Download Xray for Windows
  223. $Xray_URL = "https://github.com/XTLS/Xray-core/releases/download/v26.2.6/"
  224. Invoke-WebRequest -Uri "${Xray_URL}Xray-windows-64.zip" -OutFile "Xray-windows-64.zip"
  225. Expand-Archive -Path "Xray-windows-64.zip" -DestinationPath .
  226. Remove-Item "Xray-windows-64.zip"
  227. Remove-Item geoip.dat, geosite.dat -ErrorAction SilentlyContinue
  228. Invoke-WebRequest -Uri "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat" -OutFile "geoip.dat"
  229. Invoke-WebRequest -Uri "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat" -OutFile "geosite.dat"
  230. Invoke-WebRequest -Uri "https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat" -OutFile "geoip_IR.dat"
  231. Invoke-WebRequest -Uri "https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat" -OutFile "geosite_IR.dat"
  232. Invoke-WebRequest -Uri "https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat" -OutFile "geoip_RU.dat"
  233. Invoke-WebRequest -Uri "https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat" -OutFile "geosite_RU.dat"
  234. Rename-Item xray.exe xray-windows-amd64.exe
  235. cd ..
  236. Copy-Item -Path ..\windows_files\* -Destination . -Recurse
  237. cd ..
  238. - name: Package to Zip
  239. shell: pwsh
  240. run: |
  241. Compress-Archive -Path .\x-ui -DestinationPath "x-ui-windows-amd64.zip"
  242. - name: Upload files to Artifacts
  243. uses: actions/upload-artifact@v7
  244. with:
  245. name: x-ui-windows-amd64
  246. path: ./x-ui-windows-amd64.zip
  247. - name: Upload files to GH release
  248. uses: svenstaro/upload-release-action@v2
  249. if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
  250. with:
  251. repo_token: ${{ secrets.GITHUB_TOKEN }}
  252. tag: ${{ github.ref_name }}
  253. file: x-ui-windows-amd64.zip
  254. asset_name: x-ui-windows-amd64.zip
  255. overwrite: true
  256. prerelease: true