linux.yml 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. name: Build Linux Packages
  2. on:
  3. #push:
  4. # branches:
  5. # - stable
  6. # - testing
  7. workflow_dispatch:
  8. inputs:
  9. version:
  10. description: "Version name"
  11. required: true
  12. type: string
  13. release:
  14. types:
  15. - published
  16. jobs:
  17. calculate_version:
  18. name: Calculate version
  19. runs-on: ubuntu-latest
  20. outputs:
  21. version: ${{ steps.outputs.outputs.version }}
  22. steps:
  23. - name: Checkout
  24. uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
  25. with:
  26. fetch-depth: 0
  27. - name: Setup Go
  28. uses: actions/setup-go@v5
  29. with:
  30. go-version: ~1.25.8
  31. - name: Check input version
  32. if: github.event_name == 'workflow_dispatch'
  33. run: |-
  34. echo "version=${{ inputs.version }}"
  35. echo "version=${{ inputs.version }}" >> "$GITHUB_ENV"
  36. - name: Calculate version
  37. if: github.event_name != 'workflow_dispatch'
  38. run: |-
  39. go run -v ./cmd/internal/read_tag --ci --nightly
  40. - name: Set outputs
  41. id: outputs
  42. run: |-
  43. echo "version=$version" >> "$GITHUB_OUTPUT"
  44. build:
  45. name: Build binary
  46. runs-on: ubuntu-latest
  47. needs:
  48. - calculate_version
  49. strategy:
  50. matrix:
  51. include:
  52. # Naive-enabled builds (musl)
  53. - { os: linux, arch: amd64, naive: true, debian: amd64, rpm: x86_64, pacman: x86_64 }
  54. - { os: linux, arch: arm64, naive: true, debian: arm64, rpm: aarch64, pacman: aarch64 }
  55. - { os: linux, arch: "386", naive: true, debian: i386, rpm: i386 }
  56. - { os: linux, arch: arm, goarm: "7", naive: true, debian: armhf, rpm: armv7hl, pacman: armv7hl }
  57. - { os: linux, arch: mipsle, gomips: softfloat, naive: true, debian: mipsel, rpm: mipsel }
  58. - { os: linux, arch: riscv64, naive: true, debian: riscv64, rpm: riscv64 }
  59. - { os: linux, arch: loong64, naive: true, debian: loongarch64, rpm: loongarch64 }
  60. # Non-naive builds (unsupported architectures)
  61. - { os: linux, arch: arm, goarm: "6", debian: armel, rpm: armv6hl }
  62. - { os: linux, arch: mips64le, debian: mips64el, rpm: mips64el }
  63. - { os: linux, arch: s390x, debian: s390x, rpm: s390x }
  64. - { os: linux, arch: ppc64le, debian: ppc64el, rpm: ppc64le }
  65. steps:
  66. - name: Checkout
  67. uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
  68. with:
  69. fetch-depth: 0
  70. - name: Setup Go
  71. uses: actions/setup-go@v5
  72. with:
  73. go-version: ~1.25.8
  74. - name: Clone cronet-go
  75. if: matrix.naive
  76. run: |
  77. set -xeuo pipefail
  78. CRONET_GO_VERSION=$(cat .github/CRONET_GO_VERSION)
  79. git init ~/cronet-go
  80. git -C ~/cronet-go remote add origin https://github.com/sagernet/cronet-go.git
  81. git -C ~/cronet-go fetch --depth=1 origin "$CRONET_GO_VERSION"
  82. git -C ~/cronet-go checkout FETCH_HEAD
  83. git -C ~/cronet-go submodule update --init --recursive --depth=1
  84. - name: Regenerate Debian keyring
  85. if: matrix.naive
  86. run: |
  87. set -xeuo pipefail
  88. rm -f ~/cronet-go/naiveproxy/src/build/linux/sysroot_scripts/keyring.gpg
  89. cd ~/cronet-go
  90. GPG_TTY=/dev/null ./naiveproxy/src/build/linux/sysroot_scripts/generate_keyring.sh
  91. - name: Cache Chromium toolchain
  92. if: matrix.naive
  93. id: cache-chromium-toolchain
  94. uses: actions/cache@v4
  95. with:
  96. path: |
  97. ~/cronet-go/naiveproxy/src/third_party/llvm-build/
  98. ~/cronet-go/naiveproxy/src/gn/out/
  99. ~/cronet-go/naiveproxy/src/chrome/build/pgo_profiles/
  100. ~/cronet-go/naiveproxy/src/out/sysroot-build/
  101. key: chromium-toolchain-${{ matrix.arch }}-musl-${{ hashFiles('.github/CRONET_GO_VERSION') }}
  102. - name: Download Chromium toolchain
  103. if: matrix.naive
  104. run: |
  105. set -xeuo pipefail
  106. cd ~/cronet-go
  107. go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl download-toolchain
  108. - name: Set Chromium toolchain environment
  109. if: matrix.naive
  110. run: |
  111. set -xeuo pipefail
  112. cd ~/cronet-go
  113. go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl env >> $GITHUB_ENV
  114. - name: Set tag
  115. run: |-
  116. git ls-remote --exit-code --tags origin v${{ needs.calculate_version.outputs.version }} || echo "PUBLISHED=false" >> "$GITHUB_ENV"
  117. git tag v${{ needs.calculate_version.outputs.version }} -f
  118. - name: Set build tags
  119. run: |
  120. set -xeuo pipefail
  121. if [[ "${{ matrix.naive }}" == "true" ]]; then
  122. TAGS="$(cat release/DEFAULT_BUILD_TAGS),with_musl"
  123. else
  124. TAGS=$(cat release/DEFAULT_BUILD_TAGS_OTHERS)
  125. fi
  126. echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}"
  127. - name: Set shared ldflags
  128. run: |
  129. echo "LDFLAGS_SHARED=$(cat release/LDFLAGS)" >> "${GITHUB_ENV}"
  130. - name: Build (naive)
  131. if: matrix.naive
  132. run: |
  133. set -xeuo pipefail
  134. mkdir -p dist
  135. go build -v -trimpath -o dist/sing-box -tags "${BUILD_TAGS}" \
  136. -ldflags "-X 'github.com/sagernet/sing-box/constant.Version=${{ needs.calculate_version.outputs.version }}' ${LDFLAGS_SHARED} -s -w -buildid=" \
  137. ./cmd/sing-box
  138. env:
  139. CGO_ENABLED: "1"
  140. GOOS: linux
  141. GOARCH: ${{ matrix.arch }}
  142. GOARM: ${{ matrix.goarm }}
  143. GOMIPS: ${{ matrix.gomips }}
  144. GOMIPS64: ${{ matrix.gomips }}
  145. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  146. - name: Build (non-naive)
  147. if: ${{ ! matrix.naive }}
  148. run: |
  149. set -xeuo pipefail
  150. mkdir -p dist
  151. go build -v -trimpath -o dist/sing-box -tags "${BUILD_TAGS}" \
  152. -ldflags "-X 'github.com/sagernet/sing-box/constant.Version=${{ needs.calculate_version.outputs.version }}' ${LDFLAGS_SHARED} -s -w -buildid=" \
  153. ./cmd/sing-box
  154. env:
  155. CGO_ENABLED: "0"
  156. GOOS: ${{ matrix.os }}
  157. GOARCH: ${{ matrix.arch }}
  158. GOARM: ${{ matrix.goarm }}
  159. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  160. - name: Set mtime
  161. run: |-
  162. TZ=UTC touch -t '197001010000' dist/sing-box
  163. - name: Detect track
  164. run: bash .github/detect_track.sh
  165. - name: Set version
  166. run: |-
  167. PKG_VERSION="${{ needs.calculate_version.outputs.version }}"
  168. PKG_VERSION="${PKG_VERSION//-/\~}"
  169. echo "PKG_VERSION=${PKG_VERSION}" >> "${GITHUB_ENV}"
  170. - name: Package DEB
  171. if: matrix.debian != ''
  172. run: |
  173. set -xeuo pipefail
  174. sudo gem install fpm
  175. sudo apt-get install -y debsigs
  176. cp .fpm_systemd .fpm
  177. fpm -t deb \
  178. --name "${NAME}" \
  179. -v "$PKG_VERSION" \
  180. -p "dist/${NAME}_${{ needs.calculate_version.outputs.version }}_linux_${{ matrix.debian }}.deb" \
  181. --architecture ${{ matrix.debian }} \
  182. dist/sing-box=/usr/bin/sing-box
  183. curl -Lo '/tmp/debsigs.diff' 'https://gitlab.com/debsigs/debsigs/-/commit/160138f5de1ec110376d3c807b60a37388bc7c90.diff'
  184. sudo patch /usr/bin/debsigs < '/tmp/debsigs.diff'
  185. rm -rf $HOME/.gnupg
  186. gpg --pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}" --import <<EOF
  187. ${{ secrets.GPG_KEY }}
  188. EOF
  189. debsigs --sign=origin -k ${{ secrets.GPG_KEY_ID }} --gpgopts '--pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}"' dist/*.deb
  190. - name: Package RPM
  191. if: matrix.rpm != ''
  192. run: |-
  193. set -xeuo pipefail
  194. sudo gem install fpm
  195. cp .fpm_systemd .fpm
  196. fpm -t rpm \
  197. --name "${NAME}" \
  198. -v "$PKG_VERSION" \
  199. -p "dist/${NAME}_${{ needs.calculate_version.outputs.version }}_linux_${{ matrix.rpm }}.rpm" \
  200. --architecture ${{ matrix.rpm }} \
  201. dist/sing-box=/usr/bin/sing-box
  202. cat > $HOME/.rpmmacros <<EOF
  203. %_gpg_name ${{ secrets.GPG_KEY_ID }}
  204. %_gpg_sign_cmd_extra_args --pinentry-mode loopback --passphrase ${{ secrets.GPG_PASSPHRASE }}
  205. EOF
  206. gpg --pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}" --import <<EOF
  207. ${{ secrets.GPG_KEY }}
  208. EOF
  209. rpmsign --addsign dist/*.rpm
  210. - name: Cleanup
  211. run: rm dist/sing-box
  212. - name: Upload artifact
  213. uses: actions/upload-artifact@v4
  214. with:
  215. name: binary-${{ matrix.os }}_${{ matrix.arch }}${{ matrix.goarm && format('v{0}', matrix.goarm) }}${{ matrix.legacy_go && '-legacy' || '' }}
  216. path: "dist"
  217. upload:
  218. name: Upload builds
  219. runs-on: ubuntu-latest
  220. needs:
  221. - calculate_version
  222. - build
  223. steps:
  224. - name: Checkout
  225. uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
  226. with:
  227. fetch-depth: 0
  228. - name: Set tag
  229. run: |-
  230. git ls-remote --exit-code --tags origin v${{ needs.calculate_version.outputs.version }} || echo "PUBLISHED=false" >> "$GITHUB_ENV"
  231. git tag v${{ needs.calculate_version.outputs.version }} -f
  232. echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV"
  233. - name: Download builds
  234. uses: actions/download-artifact@v5
  235. with:
  236. path: dist
  237. merge-multiple: true
  238. - name: Publish packages
  239. if: github.event_name != 'push'
  240. run: |-
  241. ls dist | xargs -I {} curl -F "package=@dist/{}" https://${{ secrets.FURY_TOKEN }}@push.fury.io/sagernet/