linux.yml 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. name: Build Linux Packages
  2. on:
  3. workflow_dispatch:
  4. inputs:
  5. version:
  6. description: "Version name"
  7. required: true
  8. type: string
  9. forceBeta:
  10. description: "Force beta"
  11. required: false
  12. type: boolean
  13. default: false
  14. release:
  15. types:
  16. - published
  17. jobs:
  18. calculate_version:
  19. name: Calculate version
  20. runs-on: ubuntu-latest
  21. outputs:
  22. version: ${{ steps.outputs.outputs.version }}
  23. steps:
  24. - name: Checkout
  25. uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
  26. with:
  27. fetch-depth: 0
  28. - name: Setup Go
  29. uses: actions/setup-go@v5
  30. with:
  31. go-version: ^1.25.3
  32. - name: Check input version
  33. if: github.event_name == 'workflow_dispatch'
  34. run: |-
  35. echo "version=${{ inputs.version }}"
  36. echo "version=${{ inputs.version }}" >> "$GITHUB_ENV"
  37. - name: Calculate version
  38. if: github.event_name != 'workflow_dispatch'
  39. run: |-
  40. go run -v ./cmd/internal/read_tag --ci --nightly
  41. - name: Set outputs
  42. id: outputs
  43. run: |-
  44. echo "version=$version" >> "$GITHUB_OUTPUT"
  45. build:
  46. name: Build binary
  47. runs-on: ubuntu-latest
  48. needs:
  49. - calculate_version
  50. strategy:
  51. matrix:
  52. include:
  53. - { os: linux, arch: amd64, debian: amd64, rpm: x86_64, pacman: x86_64 }
  54. - { os: linux, arch: "386", debian: i386, rpm: i386 }
  55. - { os: linux, arch: arm, goarm: "6", debian: armel, rpm: armv6hl }
  56. - { os: linux, arch: arm, goarm: "7", debian: armhf, rpm: armv7hl, pacman: armv7hl }
  57. - { os: linux, arch: arm64, debian: arm64, rpm: aarch64, pacman: aarch64 }
  58. - { os: linux, arch: mips64le, debian: mips64el, rpm: mips64el }
  59. - { os: linux, arch: mipsle, debian: mipsel, rpm: mipsel }
  60. - { os: linux, arch: s390x, debian: s390x, rpm: s390x }
  61. - { os: linux, arch: ppc64le, debian: ppc64el, rpm: ppc64le }
  62. - { os: linux, arch: riscv64, debian: riscv64, rpm: riscv64 }
  63. - { os: linux, arch: loong64, debian: loongarch64, rpm: loongarch64 }
  64. steps:
  65. - name: Checkout
  66. uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
  67. with:
  68. fetch-depth: 0
  69. - name: Setup Go
  70. uses: actions/setup-go@v5
  71. with:
  72. go-version: ^1.25.3
  73. - name: Setup Android NDK
  74. if: matrix.os == 'android'
  75. uses: nttld/setup-ndk@v1
  76. with:
  77. ndk-version: r28
  78. local-cache: true
  79. - name: Set tag
  80. run: |-
  81. git ls-remote --exit-code --tags origin v${{ needs.calculate_version.outputs.version }} || echo "PUBLISHED=false" >> "$GITHUB_ENV"
  82. git tag v${{ needs.calculate_version.outputs.version }} -f
  83. - name: Set build tags
  84. run: |
  85. set -xeuo pipefail
  86. TAGS='with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_acme,with_clash_api,with_tailscale,badlinkname'
  87. echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}"
  88. - name: Build
  89. run: |
  90. set -xeuo pipefail
  91. mkdir -p dist
  92. go build -v -trimpath -o dist/sing-box -tags "${BUILD_TAGS}" \
  93. -ldflags '-s -buildid= -X github.com/sagernet/sing-box/constant.Version=${{ needs.calculate_version.outputs.version }} -checklinkname=0' \
  94. ./cmd/sing-box
  95. env:
  96. CGO_ENABLED: "0"
  97. GOOS: ${{ matrix.os }}
  98. GOARCH: ${{ matrix.arch }}
  99. GOARM: ${{ matrix.goarm }}
  100. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  101. - name: Set mtime
  102. run: |-
  103. TZ=UTC touch -t '197001010000' dist/sing-box
  104. - name: Set name
  105. if: (! contains(needs.calculate_version.outputs.version, '-')) && !inputs.forceBeta
  106. run: |-
  107. echo "NAME=sing-box" >> "$GITHUB_ENV"
  108. - name: Set beta name
  109. if: contains(needs.calculate_version.outputs.version, '-') || inputs.forceBeta
  110. run: |-
  111. echo "NAME=sing-box-beta" >> "$GITHUB_ENV"
  112. - name: Set version
  113. run: |-
  114. PKG_VERSION="${{ needs.calculate_version.outputs.version }}"
  115. PKG_VERSION="${PKG_VERSION//-/\~}"
  116. echo "PKG_VERSION=${PKG_VERSION}" >> "${GITHUB_ENV}"
  117. - name: Package DEB
  118. if: matrix.debian != ''
  119. run: |
  120. set -xeuo pipefail
  121. sudo gem install fpm
  122. sudo apt-get install -y debsigs
  123. cp .fpm_systemd .fpm
  124. fpm -t deb \
  125. --name "${NAME}" \
  126. -v "$PKG_VERSION" \
  127. -p "dist/${NAME}_${{ needs.calculate_version.outputs.version }}_linux_${{ matrix.debian }}.deb" \
  128. --architecture ${{ matrix.debian }} \
  129. dist/sing-box=/usr/bin/sing-box
  130. curl -Lo '/tmp/debsigs.diff' 'https://gitlab.com/debsigs/debsigs/-/commit/160138f5de1ec110376d3c807b60a37388bc7c90.diff'
  131. sudo patch /usr/bin/debsigs < '/tmp/debsigs.diff'
  132. rm -rf $HOME/.gnupg
  133. gpg --pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}" --import <<EOF
  134. ${{ secrets.GPG_KEY }}
  135. EOF
  136. debsigs --sign=origin -k ${{ secrets.GPG_KEY_ID }} --gpgopts '--pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}"' dist/*.deb
  137. - name: Package RPM
  138. if: matrix.rpm != ''
  139. run: |-
  140. set -xeuo pipefail
  141. sudo gem install fpm
  142. cp .fpm_systemd .fpm
  143. fpm -t rpm \
  144. --name "${NAME}" \
  145. -v "$PKG_VERSION" \
  146. -p "dist/${NAME}_${{ needs.calculate_version.outputs.version }}_linux_${{ matrix.rpm }}.rpm" \
  147. --architecture ${{ matrix.rpm }} \
  148. dist/sing-box=/usr/bin/sing-box
  149. cat > $HOME/.rpmmacros <<EOF
  150. %_gpg_name ${{ secrets.GPG_KEY_ID }}
  151. %_gpg_sign_cmd_extra_args --pinentry-mode loopback --passphrase ${{ secrets.GPG_PASSPHRASE }}
  152. EOF
  153. gpg --pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}" --import <<EOF
  154. ${{ secrets.GPG_KEY }}
  155. EOF
  156. rpmsign --addsign dist/*.rpm
  157. - name: Cleanup
  158. run: rm dist/sing-box
  159. - name: Upload artifact
  160. uses: actions/upload-artifact@v4
  161. with:
  162. name: binary-${{ matrix.os }}_${{ matrix.arch }}${{ matrix.goarm && format('v{0}', matrix.goarm) }}${{ matrix.legacy_go && '-legacy' || '' }}
  163. path: "dist"
  164. upload:
  165. name: Upload builds
  166. runs-on: ubuntu-latest
  167. needs:
  168. - calculate_version
  169. - build
  170. steps:
  171. - name: Checkout
  172. uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
  173. with:
  174. fetch-depth: 0
  175. - name: Set tag
  176. run: |-
  177. git ls-remote --exit-code --tags origin v${{ needs.calculate_version.outputs.version }} || echo "PUBLISHED=false" >> "$GITHUB_ENV"
  178. git tag v${{ needs.calculate_version.outputs.version }} -f
  179. echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV"
  180. - name: Download builds
  181. uses: actions/download-artifact@v5
  182. with:
  183. path: dist
  184. merge-multiple: true
  185. - name: Publish packages
  186. run: |-
  187. ls dist | xargs -I {} curl -F "package=@dist/{}" https://${{ secrets.FURY_TOKEN }}@push.fury.io/sagernet/