docker.yml 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. name: Publish Docker Images
  2. on:
  3. #push:
  4. # branches:
  5. # - main-next
  6. # - dev-next
  7. release:
  8. types:
  9. - published
  10. workflow_dispatch:
  11. inputs:
  12. tag:
  13. description: "The tag version you want to build"
  14. env:
  15. REGISTRY_IMAGE: ghcr.io/sagernet/sing-box
  16. jobs:
  17. build_binary:
  18. name: Build binary
  19. runs-on: ubuntu-latest
  20. strategy:
  21. fail-fast: true
  22. matrix:
  23. include:
  24. # Naive-enabled builds (musl)
  25. - { arch: amd64, naive: true, docker_platform: "linux/amd64" }
  26. - { arch: arm64, naive: true, docker_platform: "linux/arm64" }
  27. - { arch: "386", naive: true, docker_platform: "linux/386" }
  28. - { arch: arm, goarm: "7", naive: true, docker_platform: "linux/arm/v7" }
  29. # Non-naive builds
  30. - { arch: arm, goarm: "6", docker_platform: "linux/arm/v6" }
  31. - { arch: ppc64le, docker_platform: "linux/ppc64le" }
  32. - { arch: riscv64, docker_platform: "linux/riscv64" }
  33. - { arch: s390x, docker_platform: "linux/s390x" }
  34. steps:
  35. - name: Get commit to build
  36. id: ref
  37. run: |-
  38. if [[ -z "${{ github.event.inputs.tag }}" ]]; then
  39. ref="${{ github.ref_name }}"
  40. else
  41. ref="${{ github.event.inputs.tag }}"
  42. fi
  43. echo "ref=$ref"
  44. echo "ref=$ref" >> $GITHUB_OUTPUT
  45. - name: Checkout
  46. uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
  47. with:
  48. ref: ${{ steps.ref.outputs.ref }}
  49. fetch-depth: 0
  50. - name: Setup Go
  51. uses: actions/setup-go@v5
  52. with:
  53. go-version: ^1.25.4
  54. - name: Clone cronet-go
  55. if: matrix.naive
  56. run: |
  57. set -xeuo pipefail
  58. CRONET_GO_VERSION=$(cat .github/CRONET_GO_VERSION)
  59. git init ~/cronet-go
  60. git -C ~/cronet-go remote add origin https://github.com/sagernet/cronet-go.git
  61. git -C ~/cronet-go fetch --depth=1 origin "$CRONET_GO_VERSION"
  62. git -C ~/cronet-go checkout FETCH_HEAD
  63. git -C ~/cronet-go submodule update --init --recursive --depth=1
  64. - name: Cache Chromium toolchain
  65. if: matrix.naive
  66. id: cache-chromium-toolchain
  67. uses: actions/cache@v4
  68. with:
  69. path: |
  70. ~/cronet-go/naiveproxy/src/third_party/llvm-build/Release+Asserts
  71. ~/cronet-go/naiveproxy/src/out/sysroot-build
  72. key: chromium-toolchain-${{ matrix.arch }}-musl-${{ hashFiles('.github/CRONET_GO_VERSION') }}
  73. - name: Download Chromium toolchain
  74. if: matrix.naive
  75. run: |
  76. set -xeuo pipefail
  77. cd ~/cronet-go
  78. go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl download-toolchain
  79. - name: Set version
  80. run: |
  81. set -xeuo pipefail
  82. VERSION=$(go run ./cmd/internal/read_tag)
  83. echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
  84. - name: Set Chromium toolchain environment
  85. if: matrix.naive
  86. run: |
  87. set -xeuo pipefail
  88. cd ~/cronet-go
  89. go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl env >> $GITHUB_ENV
  90. - name: Set build tags
  91. run: |
  92. set -xeuo pipefail
  93. TAGS='with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_acme,with_clash_api,with_tailscale,with_ccm,with_ocm,badlinkname,tfogo_checklinkname0'
  94. if [[ "${{ matrix.naive }}" == "true" ]]; then
  95. TAGS="${TAGS},with_naive_outbound,with_musl"
  96. fi
  97. echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}"
  98. - name: Build (naive)
  99. if: matrix.naive
  100. run: |
  101. set -xeuo pipefail
  102. go build -v -trimpath -o sing-box -tags "${BUILD_TAGS}" \
  103. -ldflags "-X \"github.com/sagernet/sing-box/constant.Version=${VERSION}\" -s -w -buildid= -checklinkname=0" \
  104. ./cmd/sing-box
  105. env:
  106. CGO_ENABLED: "1"
  107. GOOS: linux
  108. GOARCH: ${{ matrix.arch }}
  109. GOARM: ${{ matrix.goarm }}
  110. - name: Build (non-naive)
  111. if: ${{ ! matrix.naive }}
  112. run: |
  113. set -xeuo pipefail
  114. go build -v -trimpath -o sing-box -tags "${BUILD_TAGS}" \
  115. -ldflags "-X \"github.com/sagernet/sing-box/constant.Version=${VERSION}\" -s -w -buildid= -checklinkname=0" \
  116. ./cmd/sing-box
  117. env:
  118. CGO_ENABLED: "0"
  119. GOOS: linux
  120. GOARCH: ${{ matrix.arch }}
  121. GOARM: ${{ matrix.goarm }}
  122. - name: Prepare artifact
  123. run: |
  124. platform=${{ matrix.docker_platform }}
  125. echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
  126. # Rename binary to include arch info for Dockerfile.binary
  127. BINARY_NAME="sing-box-${{ matrix.arch }}"
  128. if [[ -n "${{ matrix.goarm }}" ]]; then
  129. BINARY_NAME="${BINARY_NAME}v${{ matrix.goarm }}"
  130. fi
  131. mv sing-box "${BINARY_NAME}"
  132. echo "BINARY_NAME=${BINARY_NAME}" >> $GITHUB_ENV
  133. - name: Upload binary
  134. uses: actions/upload-artifact@v4
  135. with:
  136. name: binary-${{ env.PLATFORM_PAIR }}
  137. path: ${{ env.BINARY_NAME }}
  138. if-no-files-found: error
  139. retention-days: 1
  140. build_docker:
  141. name: Build Docker image
  142. runs-on: ubuntu-latest
  143. needs:
  144. - build_binary
  145. strategy:
  146. fail-fast: true
  147. matrix:
  148. platform:
  149. - linux/amd64
  150. - linux/arm/v6
  151. - linux/arm/v7
  152. - linux/arm64
  153. - linux/386
  154. - linux/ppc64le
  155. - linux/riscv64
  156. - linux/s390x
  157. steps:
  158. - name: Get commit to build
  159. id: ref
  160. run: |-
  161. if [[ -z "${{ github.event.inputs.tag }}" ]]; then
  162. ref="${{ github.ref_name }}"
  163. else
  164. ref="${{ github.event.inputs.tag }}"
  165. fi
  166. echo "ref=$ref"
  167. echo "ref=$ref" >> $GITHUB_OUTPUT
  168. - name: Checkout
  169. uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
  170. with:
  171. ref: ${{ steps.ref.outputs.ref }}
  172. fetch-depth: 0
  173. - name: Prepare
  174. run: |
  175. platform=${{ matrix.platform }}
  176. echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
  177. - name: Download binary
  178. uses: actions/download-artifact@v5
  179. with:
  180. name: binary-${{ env.PLATFORM_PAIR }}
  181. path: .
  182. - name: Prepare binary
  183. run: |
  184. # Find and make the binary executable
  185. chmod +x sing-box-*
  186. ls -la sing-box-*
  187. - name: Setup QEMU
  188. uses: docker/setup-qemu-action@v3
  189. - name: Setup Docker Buildx
  190. uses: docker/setup-buildx-action@v3
  191. - name: Login to GitHub Container Registry
  192. uses: docker/login-action@v3
  193. with:
  194. registry: ghcr.io
  195. username: ${{ github.repository_owner }}
  196. password: ${{ secrets.GITHUB_TOKEN }}
  197. - name: Docker meta
  198. id: meta
  199. uses: docker/metadata-action@v5
  200. with:
  201. images: ${{ env.REGISTRY_IMAGE }}
  202. - name: Build and push by digest
  203. id: build
  204. uses: docker/build-push-action@v6
  205. with:
  206. platforms: ${{ matrix.platform }}
  207. context: .
  208. file: Dockerfile.binary
  209. labels: ${{ steps.meta.outputs.labels }}
  210. outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
  211. - name: Export digest
  212. run: |
  213. mkdir -p /tmp/digests
  214. digest="${{ steps.build.outputs.digest }}"
  215. touch "/tmp/digests/${digest#sha256:}"
  216. - name: Upload digest
  217. uses: actions/upload-artifact@v4
  218. with:
  219. name: digests-${{ env.PLATFORM_PAIR }}
  220. path: /tmp/digests/*
  221. if-no-files-found: error
  222. retention-days: 1
  223. merge:
  224. runs-on: ubuntu-latest
  225. needs:
  226. - build_docker
  227. steps:
  228. - name: Get commit to build
  229. id: ref
  230. run: |-
  231. if [[ -z "${{ github.event.inputs.tag }}" ]]; then
  232. ref="${{ github.ref_name }}"
  233. else
  234. ref="${{ github.event.inputs.tag }}"
  235. fi
  236. echo "ref=$ref"
  237. echo "ref=$ref" >> $GITHUB_OUTPUT
  238. if [[ $ref == *"-"* ]]; then
  239. latest=latest-beta
  240. else
  241. latest=latest
  242. fi
  243. echo "latest=$latest"
  244. echo "latest=$latest" >> $GITHUB_OUTPUT
  245. - name: Download digests
  246. uses: actions/download-artifact@v5
  247. with:
  248. path: /tmp/digests
  249. pattern: digests-*
  250. merge-multiple: true
  251. - name: Set up Docker Buildx
  252. uses: docker/setup-buildx-action@v3
  253. - name: Login to GitHub Container Registry
  254. uses: docker/login-action@v3
  255. with:
  256. registry: ghcr.io
  257. username: ${{ github.repository_owner }}
  258. password: ${{ secrets.GITHUB_TOKEN }}
  259. - name: Create manifest list and push
  260. if: github.event_name != 'push'
  261. working-directory: /tmp/digests
  262. run: |
  263. docker buildx imagetools create \
  264. -t "${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.latest }}" \
  265. -t "${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.ref }}" \
  266. $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
  267. - name: Inspect image
  268. if: github.event_name != 'push'
  269. run: |
  270. docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.latest }}
  271. docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.ref }}