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