name: Build Linux Packages on: #push: # branches: # - main-next # - dev-next workflow_dispatch: inputs: version: description: "Version name" required: true type: string forceBeta: description: "Force beta" required: false type: boolean default: false release: types: - published jobs: calculate_version: name: Calculate version runs-on: ubuntu-latest outputs: version: ${{ steps.outputs.outputs.version }} steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 with: fetch-depth: 0 - name: Setup Go uses: actions/setup-go@v5 with: go-version: ~1.25.7 - name: Check input version if: github.event_name == 'workflow_dispatch' run: |- echo "version=${{ inputs.version }}" echo "version=${{ inputs.version }}" >> "$GITHUB_ENV" - name: Calculate version if: github.event_name != 'workflow_dispatch' run: |- go run -v ./cmd/internal/read_tag --ci --nightly - name: Set outputs id: outputs run: |- echo "version=$version" >> "$GITHUB_OUTPUT" build: name: Build binary runs-on: ubuntu-latest needs: - calculate_version strategy: matrix: include: # Naive-enabled builds (musl) - { os: linux, arch: amd64, naive: true, debian: amd64, rpm: x86_64, pacman: x86_64 } - { os: linux, arch: arm64, naive: true, debian: arm64, rpm: aarch64, pacman: aarch64 } - { os: linux, arch: "386", naive: true, debian: i386, rpm: i386 } - { os: linux, arch: arm, goarm: "7", naive: true, debian: armhf, rpm: armv7hl, pacman: armv7hl } - { os: linux, arch: mipsle, gomips: softfloat, naive: true, debian: mipsel, rpm: mipsel } - { os: linux, arch: riscv64, naive: true, debian: riscv64, rpm: riscv64 } - { os: linux, arch: loong64, naive: true, debian: loongarch64, rpm: loongarch64 } # Non-naive builds (unsupported architectures) - { os: linux, arch: arm, goarm: "6", debian: armel, rpm: armv6hl } - { os: linux, arch: mips64le, debian: mips64el, rpm: mips64el } - { os: linux, arch: s390x, debian: s390x, rpm: s390x } - { os: linux, arch: ppc64le, debian: ppc64el, rpm: ppc64le } steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 with: fetch-depth: 0 - name: Setup Go uses: actions/setup-go@v5 with: go-version: ~1.25.7 - name: Clone cronet-go if: matrix.naive run: | set -xeuo pipefail CRONET_GO_VERSION=$(cat .github/CRONET_GO_VERSION) git init ~/cronet-go git -C ~/cronet-go remote add origin https://github.com/sagernet/cronet-go.git git -C ~/cronet-go fetch --depth=1 origin "$CRONET_GO_VERSION" git -C ~/cronet-go checkout FETCH_HEAD git -C ~/cronet-go submodule update --init --recursive --depth=1 - name: Regenerate Debian keyring if: matrix.naive run: | set -xeuo pipefail rm -f ~/cronet-go/naiveproxy/src/build/linux/sysroot_scripts/keyring.gpg cd ~/cronet-go GPG_TTY=/dev/null ./naiveproxy/src/build/linux/sysroot_scripts/generate_keyring.sh - name: Cache Chromium toolchain if: matrix.naive id: cache-chromium-toolchain uses: actions/cache@v4 with: path: | ~/cronet-go/naiveproxy/src/third_party/llvm-build/ ~/cronet-go/naiveproxy/src/gn/out/ ~/cronet-go/naiveproxy/src/chrome/build/pgo_profiles/ ~/cronet-go/naiveproxy/src/out/sysroot-build/ key: chromium-toolchain-${{ matrix.arch }}-musl-${{ hashFiles('.github/CRONET_GO_VERSION') }} - name: Download Chromium toolchain if: matrix.naive run: | set -xeuo pipefail cd ~/cronet-go go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl download-toolchain - name: Set Chromium toolchain environment if: matrix.naive run: | set -xeuo pipefail cd ~/cronet-go go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl env >> $GITHUB_ENV - name: Set tag run: |- git ls-remote --exit-code --tags origin v${{ needs.calculate_version.outputs.version }} || echo "PUBLISHED=false" >> "$GITHUB_ENV" git tag v${{ needs.calculate_version.outputs.version }} -f - name: Set build tags run: | set -xeuo pipefail if [[ "${{ matrix.naive }}" == "true" ]]; then TAGS="$(cat release/DEFAULT_BUILD_TAGS),with_musl" else TAGS=$(cat release/DEFAULT_BUILD_TAGS_OTHERS) fi echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}" - name: Set shared ldflags run: | echo "LDFLAGS_SHARED=$(cat release/LDFLAGS)" >> "${GITHUB_ENV}" - name: Build (naive) if: matrix.naive run: | set -xeuo pipefail mkdir -p dist go build -v -trimpath -o dist/sing-box -tags "${BUILD_TAGS}" \ -ldflags "-X 'github.com/sagernet/sing-box/constant.Version=${{ needs.calculate_version.outputs.version }}' ${LDFLAGS_SHARED} -s -w -buildid=" \ ./cmd/sing-box env: CGO_ENABLED: "1" GOOS: linux GOARCH: ${{ matrix.arch }} GOARM: ${{ matrix.goarm }} GOMIPS: ${{ matrix.gomips }} GOMIPS64: ${{ matrix.gomips }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build (non-naive) if: ${{ ! matrix.naive }} run: | set -xeuo pipefail mkdir -p dist go build -v -trimpath -o dist/sing-box -tags "${BUILD_TAGS}" \ -ldflags "-X 'github.com/sagernet/sing-box/constant.Version=${{ needs.calculate_version.outputs.version }}' ${LDFLAGS_SHARED} -s -w -buildid=" \ ./cmd/sing-box env: CGO_ENABLED: "0" GOOS: ${{ matrix.os }} GOARCH: ${{ matrix.arch }} GOARM: ${{ matrix.goarm }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Set mtime run: |- TZ=UTC touch -t '197001010000' dist/sing-box - name: Set name if: (! contains(needs.calculate_version.outputs.version, '-')) && !inputs.forceBeta run: |- echo "NAME=sing-box" >> "$GITHUB_ENV" - name: Set beta name if: contains(needs.calculate_version.outputs.version, '-') || inputs.forceBeta run: |- echo "NAME=sing-box-beta" >> "$GITHUB_ENV" - name: Set version run: |- PKG_VERSION="${{ needs.calculate_version.outputs.version }}" PKG_VERSION="${PKG_VERSION//-/\~}" echo "PKG_VERSION=${PKG_VERSION}" >> "${GITHUB_ENV}" - name: Package DEB if: matrix.debian != '' run: | set -xeuo pipefail sudo gem install fpm sudo apt-get install -y debsigs cp .fpm_systemd .fpm fpm -t deb \ --name "${NAME}" \ -v "$PKG_VERSION" \ -p "dist/${NAME}_${{ needs.calculate_version.outputs.version }}_linux_${{ matrix.debian }}.deb" \ --architecture ${{ matrix.debian }} \ dist/sing-box=/usr/bin/sing-box curl -Lo '/tmp/debsigs.diff' 'https://gitlab.com/debsigs/debsigs/-/commit/160138f5de1ec110376d3c807b60a37388bc7c90.diff' sudo patch /usr/bin/debsigs < '/tmp/debsigs.diff' rm -rf $HOME/.gnupg gpg --pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}" --import < $HOME/.rpmmacros <> "$GITHUB_ENV" git tag v${{ needs.calculate_version.outputs.version }} -f echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV" - name: Download builds uses: actions/download-artifact@v5 with: path: dist merge-multiple: true - name: Publish packages if: github.event_name != 'push' run: |- ls dist | xargs -I {} curl -F "package=@dist/{}" https://${{ secrets.FURY_TOKEN }}@push.fury.io/sagernet/