Build #2339
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Build | |
on: | |
workflow_dispatch: | |
inputs: | |
version: | |
description: "Version name" | |
required: true | |
type: string | |
build: | |
description: "Build type" | |
required: true | |
type: choice | |
default: "All" | |
options: | |
- All | |
- Binary | |
- Android | |
- Apple | |
- app-store | |
- iOS | |
- macOS | |
- tvOS | |
- macOS-standalone | |
- publish-android | |
push: | |
branches: | |
- main-next | |
- dev-next | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}-${{ inputs.build }} | |
cancel-in-progress: true | |
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.1 | |
- 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 | |
if: github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Binary' | |
runs-on: ubuntu-latest | |
needs: | |
- calculate_version | |
strategy: | |
matrix: | |
include: | |
- { os: linux, arch: amd64, debian: amd64, rpm: x86_64, pacman: x86_64, openwrt: "x86_64" } | |
- { os: linux, arch: "386", go386: sse2, debian: i386, rpm: i386, openwrt: "i386_pentium4" } | |
- { os: linux, arch: "386", go386: softfloat, openwrt: "i386_pentium-mmx" } | |
- { os: linux, arch: arm64, debian: arm64, rpm: aarch64, pacman: aarch64, openwrt: "aarch64_cortex-a53 aarch64_cortex-a72 aarch64_cortex-a76 aarch64_generic" } | |
- { os: linux, arch: arm, goarm: "5", openwrt: "arm_arm926ej-s arm_cortex-a7 arm_cortex-a9 arm_fa526 arm_xscale" } | |
- { os: linux, arch: arm, goarm: "6", debian: armel, rpm: armv6hl, openwrt: "arm_arm1176jzf-s_vfp" } | |
- { os: linux, arch: arm, goarm: "7", debian: armhf, rpm: armv7hl, pacman: armv7hl, openwrt: "arm_cortex-a5_vfpv4 arm_cortex-a7_neon-vfpv4 arm_cortex-a7_vfpv4 arm_cortex-a8_vfpv3 arm_cortex-a9_neon arm_cortex-a9_vfpv3-d16 arm_cortex-a15_neon-vfpv4" } | |
- { os: linux, arch: mips, gomips: softfloat, openwrt: "mips_24kc mips_4kec mips_mips32" } | |
- { os: linux, arch: mipsle, gomips: hardfloat, debian: mipsel, rpm: mipsel, openwrt: "mipsel_24kc_24kf" } | |
- { os: linux, arch: mipsle, gomips: softfloat, openwrt: "mipsel_24kc mipsel_74kc mipsel_mips32" } | |
- { os: linux, arch: mips64, gomips: softfloat, openwrt: "mips64_mips64r2 mips64_octeonplus" } | |
- { os: linux, arch: mips64le, gomips: hardfloat, debian: mips64el, rpm: mips64el } | |
- { os: linux, arch: mips64le, gomips: softfloat, openwrt: "mips64el_mips64r2" } | |
- { os: linux, arch: s390x, debian: s390x, rpm: s390x } | |
- { os: linux, arch: ppc64le, debian: ppc64el, rpm: ppc64le } | |
- { os: linux, arch: riscv64, debian: riscv64, rpm: riscv64, openwrt: "riscv64_generic" } | |
- { os: linux, arch: loong64, debian: loongarch64, rpm: loongarch64, openwrt: "loongarch64_generic" } | |
- { os: windows, arch: amd64 } | |
- { os: windows, arch: amd64, legacy_win7: true, legacy_name: "windows-7" } | |
- { os: windows, arch: "386" } | |
- { os: windows, arch: "386", legacy_win7: true, legacy_name: "windows-7" } | |
- { os: windows, arch: arm64 } | |
- { os: darwin, arch: amd64 } | |
- { os: darwin, arch: arm64 } | |
- { os: darwin, arch: amd64, legacy_go124: true, legacy_name: "macos-11" } | |
- { os: android, arch: arm64, ndk: "aarch64-linux-android21" } | |
- { os: android, arch: arm, ndk: "armv7a-linux-androideabi21" } | |
- { os: android, arch: amd64, ndk: "x86_64-linux-android21" } | |
- { os: android, arch: "386", ndk: "i686-linux-android21" } | |
steps: | |
- name: Checkout | |
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 | |
with: | |
fetch-depth: 0 | |
- name: Setup Go | |
if: ${{ ! (matrix.legacy_go123 || matrix.legacy_go124) }} | |
uses: actions/setup-go@v5 | |
with: | |
go-version: ^1.25.1 | |
- name: Setup Go 1.24 | |
if: matrix.legacy_go124 | |
uses: actions/setup-go@v5 | |
with: | |
go-version: ~1.24.6 | |
- name: Cache Go for Windows 7 | |
if: matrix.legacy_win7 | |
id: cache-go-for-windows7 | |
uses: actions/cache@v4 | |
with: | |
path: | | |
~/go/go_win7 | |
key: go_win7_1251 | |
- name: Setup Go for Windows 7 | |
if: matrix.legacy_win7 && steps.cache-go-for-windows7.outputs.cache-hit != 'true' | |
run: |- | |
.github/setup_go_for_windows7.sh | |
- name: Setup Go for Windows 7 | |
if: matrix.legacy_win7 | |
run: |- | |
echo "PATH=$HOME/go/go_win7/bin:$PATH" >> $GITHUB_ENV | |
echo "GOROOT=$HOME/go/go_win7" >> $GITHUB_ENV | |
- name: Setup Android NDK | |
if: matrix.os == 'android' | |
uses: nttld/setup-ndk@v1 | |
with: | |
ndk-version: r28 | |
local-cache: true | |
- 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 | |
TAGS='with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_acme,with_clash_api,with_tailscale,badlinkname' | |
echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}" | |
- name: Build | |
if: matrix.os != 'android' | |
run: | | |
set -xeuo pipefail | |
mkdir -p dist | |
go build -v -trimpath -o dist/sing-box -tags "${BUILD_TAGS}" \ | |
-ldflags '-s -buildid= -X github.com/sagernet/sing-box/constant.Version=${{ needs.calculate_version.outputs.version }} -checklinkname=0' \ | |
./cmd/sing-box | |
env: | |
CGO_ENABLED: "0" | |
GOOS: ${{ matrix.os }} | |
GOARCH: ${{ matrix.arch }} | |
GO386: ${{ matrix.go386 }} | |
GOARM: ${{ matrix.goarm }} | |
GOMIPS: ${{ matrix.gomips }} | |
GOMIPS64: ${{ matrix.gomips }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Build Android | |
if: matrix.os == 'android' | |
run: | | |
set -xeuo pipefail | |
go install -v ./cmd/internal/build | |
export CC='${{ matrix.ndk }}-clang' | |
export CXX="${CC}++" | |
mkdir -p dist | |
GOOS=$BUILD_GOOS GOARCH=$BUILD_GOARCH build go build -v -trimpath -o dist/sing-box -tags "${BUILD_TAGS}" \ | |
-ldflags '-s -buildid= -X github.com/sagernet/sing-box/constant.Version=${{ needs.calculate_version.outputs.version }} -checklinkname=0' \ | |
./cmd/sing-box | |
env: | |
CGO_ENABLED: "1" | |
BUILD_GOOS: ${{ matrix.os }} | |
BUILD_GOARCH: ${{ matrix.arch }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Set name | |
run: |- | |
DIR_NAME="sing-box-${{ needs.calculate_version.outputs.version }}-${{ matrix.os }}-${{ matrix.arch }}" | |
if [[ -n "${{ matrix.goarm }}" ]]; then | |
DIR_NAME="${DIR_NAME}v${{ matrix.goarm }}" | |
elif [[ -n "${{ matrix.go386 }}" && "${{ matrix.go386 }}" != 'sse2' ]]; then | |
DIR_NAME="${DIR_NAME}-${{ matrix.go386 }}" | |
elif [[ -n "${{ matrix.gomips }}" && "${{ matrix.gomips }}" != 'hardfloat' ]]; then | |
DIR_NAME="${DIR_NAME}-${{ matrix.gomips }}" | |
elif [[ -n "${{ matrix.legacy_name }}" ]]; then | |
DIR_NAME="${DIR_NAME}-legacy-${{ matrix.legacy_name }}" | |
fi | |
echo "DIR_NAME=${DIR_NAME}" >> "${GITHUB_ENV}" | |
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 update | |
sudo apt-get install -y debsigs | |
cp .fpm_systemd .fpm | |
fpm -t deb \ | |
-v "$PKG_VERSION" \ | |
-p "dist/sing-box_${{ needs.calculate_version.outputs.version }}_${{ matrix.os }}_${{ 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 <<EOF | |
${{ secrets.GPG_KEY }} | |
EOF | |
debsigs --sign=origin -k ${{ secrets.GPG_KEY_ID }} --gpgopts '--pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}"' dist/*.deb | |
- name: Package RPM | |
if: matrix.rpm != '' | |
run: |- | |
set -xeuo pipefail | |
sudo gem install fpm | |
cp .fpm_systemd .fpm | |
fpm -t rpm \ | |
-v "$PKG_VERSION" \ | |
-p "dist/sing-box_${{ needs.calculate_version.outputs.version }}_${{ matrix.os }}_${{ matrix.rpm }}.rpm" \ | |
--architecture ${{ matrix.rpm }} \ | |
dist/sing-box=/usr/bin/sing-box | |
cat > $HOME/.rpmmacros <<EOF | |
%_gpg_name ${{ secrets.GPG_KEY_ID }} | |
%_gpg_sign_cmd_extra_args --pinentry-mode loopback --passphrase ${{ secrets.GPG_PASSPHRASE }} | |
EOF | |
gpg --pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}" --import <<EOF | |
${{ secrets.GPG_KEY }} | |
EOF | |
rpmsign --addsign dist/*.rpm | |
- name: Package Pacman | |
if: matrix.pacman != '' | |
run: |- | |
set -xeuo pipefail | |
sudo gem install fpm | |
sudo apt-get update | |
sudo apt-get install -y libarchive-tools | |
cp .fpm_systemd .fpm | |
fpm -t pacman \ | |
-v "$PKG_VERSION" \ | |
-p "dist/sing-box_${{ needs.calculate_version.outputs.version }}_${{ matrix.os }}_${{ matrix.pacman }}.pkg.tar.zst" \ | |
--architecture ${{ matrix.pacman }} \ | |
dist/sing-box=/usr/bin/sing-box | |
- name: Package OpenWrt | |
if: matrix.openwrt != '' | |
run: |- | |
set -xeuo pipefail | |
sudo gem install fpm | |
cp .fpm_openwrt .fpm | |
fpm -t deb \ | |
-v "$PKG_VERSION" \ | |
-p "dist/openwrt.deb" \ | |
--architecture all \ | |
dist/sing-box=/usr/bin/sing-box | |
for architecture in ${{ matrix.openwrt }}; do | |
.github/deb2ipk.sh "$architecture" "dist/openwrt.deb" "dist/sing-box_${{ needs.calculate_version.outputs.version }}_openwrt_${architecture}.ipk" | |
done | |
rm "dist/openwrt.deb" | |
- name: Archive | |
run: | | |
set -xeuo pipefail | |
cd dist | |
mkdir -p "${DIR_NAME}" | |
cp ../LICENSE "${DIR_NAME}" | |
if [ '${{ matrix.os }}' = 'windows' ]; then | |
cp sing-box "${DIR_NAME}/sing-box.exe" | |
zip -r "${DIR_NAME}.zip" "${DIR_NAME}" | |
else | |
cp sing-box "${DIR_NAME}" | |
tar -czvf "${DIR_NAME}.tar.gz" "${DIR_NAME}" | |
fi | |
rm -r "${DIR_NAME}" | |
- name: Cleanup | |
run: rm dist/sing-box | |
- name: Upload artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: binary-${{ matrix.os }}_${{ matrix.arch }}${{ matrix.goarm && format('v{0}', matrix.goarm) }}${{ matrix.go386 && format('_{0}', matrix.go386) }}${{ matrix.gomips && format('_{0}', matrix.gomips) }}${{ matrix.legacy_name && format('-legacy-{0}', matrix.legacy_name) }} | |
path: "dist" | |
build_android: | |
name: Build Android | |
if: github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Android' | |
runs-on: ubuntu-latest | |
needs: | |
- calculate_version | |
steps: | |
- name: Checkout | |
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 | |
with: | |
fetch-depth: 0 | |
submodules: 'recursive' | |
- name: Setup Go | |
uses: actions/setup-go@v5 | |
with: | |
go-version: ^1.25.1 | |
- name: Setup Android NDK | |
id: setup-ndk | |
uses: nttld/setup-ndk@v1 | |
with: | |
ndk-version: r28 | |
- name: Setup OpenJDK | |
run: |- | |
sudo apt update && sudo apt install -y openjdk-17-jdk-headless | |
/usr/lib/jvm/java-17-openjdk-amd64/bin/java --version | |
- 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: Build library | |
run: |- | |
make lib_install | |
export PATH="$PATH:$(go env GOPATH)/bin" | |
make lib_android | |
env: | |
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 | |
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} | |
- name: Checkout main branch | |
if: github.ref == 'refs/heads/main-next' && github.event_name != 'workflow_dispatch' | |
run: |- | |
cd clients/android | |
git checkout main | |
- name: Checkout dev branch | |
if: github.ref == 'refs/heads/dev-next' | |
run: |- | |
cd clients/android | |
git checkout dev | |
- name: Gradle cache | |
uses: actions/cache@v4 | |
with: | |
path: ~/.gradle | |
key: gradle-${{ hashFiles('**/*.gradle') }} | |
- name: Update version | |
if: github.event_name == 'workflow_dispatch' | |
run: |- | |
go run -v ./cmd/internal/update_android_version --ci | |
- name: Update nightly version | |
if: github.event_name != 'workflow_dispatch' | |
run: |- | |
go run -v ./cmd/internal/update_android_version --ci --nightly | |
- name: Build | |
run: |- | |
mkdir clients/android/app/libs | |
cp libbox.aar clients/android/app/libs | |
cd clients/android | |
./gradlew :app:assemblePlayRelease :app:assembleOtherRelease | |
env: | |
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 | |
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} | |
LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }} | |
- name: Prepare upload | |
run: |- | |
mkdir -p dist | |
cp clients/android/app/build/outputs/apk/play/release/*.apk dist | |
cp clients/android/app/build/outputs/apk/other/release/*-universal.apk dist | |
- name: Upload artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: binary-android-apks | |
path: 'dist' | |
publish_android: | |
name: Publish Android | |
if: github.event_name == 'workflow_dispatch' && inputs.build == 'publish-android' | |
runs-on: ubuntu-latest | |
needs: | |
- calculate_version | |
steps: | |
- name: Checkout | |
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 | |
with: | |
fetch-depth: 0 | |
submodules: 'recursive' | |
- name: Setup Go | |
uses: actions/setup-go@v5 | |
with: | |
go-version: ^1.25.1 | |
- name: Setup Android NDK | |
id: setup-ndk | |
uses: nttld/setup-ndk@v1 | |
with: | |
ndk-version: r28 | |
- name: Setup OpenJDK | |
run: |- | |
sudo apt update && sudo apt install -y openjdk-17-jdk-headless | |
/usr/lib/jvm/java-17-openjdk-amd64/bin/java --version | |
- 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: Build library | |
run: |- | |
make lib_install | |
export PATH="$PATH:$(go env GOPATH)/bin" | |
make lib_android | |
env: | |
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 | |
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} | |
- name: Checkout main branch | |
if: github.ref == 'refs/heads/main-next' && github.event_name != 'workflow_dispatch' | |
run: |- | |
cd clients/android | |
git checkout main | |
- name: Checkout dev branch | |
if: github.ref == 'refs/heads/dev-next' | |
run: |- | |
cd clients/android | |
git checkout dev | |
- name: Gradle cache | |
uses: actions/cache@v4 | |
with: | |
path: ~/.gradle | |
key: gradle-${{ hashFiles('**/*.gradle') }} | |
- name: Build | |
run: |- | |
go run -v ./cmd/internal/update_android_version --ci | |
mkdir clients/android/app/libs | |
cp libbox.aar clients/android/app/libs | |
cd clients/android | |
echo -n "$SERVICE_ACCOUNT_CREDENTIALS" | base64 --decode > service-account-credentials.json | |
./gradlew :app:publishPlayReleaseBundle | |
env: | |
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 | |
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} | |
LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }} | |
SERVICE_ACCOUNT_CREDENTIALS: ${{ secrets.SERVICE_ACCOUNT_CREDENTIALS }} | |
build_apple: | |
name: Build Apple clients | |
runs-on: macos-26 | |
if: false | |
needs: | |
- calculate_version | |
strategy: | |
matrix: | |
include: | |
- name: iOS | |
if: ${{ github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Apple' || inputs.build == 'app-store'|| inputs.build == 'iOS' }} | |
platform: ios | |
scheme: SFI | |
destination: 'generic/platform=iOS' | |
archive: build/SFI.xcarchive | |
upload: SFI/Upload.plist | |
- name: macOS | |
if: ${{ github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Apple' || inputs.build == 'app-store'|| inputs.build == 'macOS' }} | |
platform: macos | |
scheme: SFM | |
destination: 'generic/platform=macOS' | |
archive: build/SFM.xcarchive | |
upload: SFI/Upload.plist | |
- name: tvOS | |
if: ${{ github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Apple' || inputs.build == 'app-store'|| inputs.build == 'tvOS' }} | |
platform: tvos | |
scheme: SFT | |
destination: 'generic/platform=tvOS' | |
archive: build/SFT.xcarchive | |
upload: SFI/Upload.plist | |
- name: macOS-standalone | |
if: ${{ github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Apple' || inputs.build == 'macOS-standalone' }} | |
platform: macos | |
scheme: SFM.System | |
destination: 'generic/platform=macOS' | |
archive: build/SFM.System.xcarchive | |
export: SFM.System/Export.plist | |
export_path: build/SFM.System | |
steps: | |
- name: Checkout | |
if: matrix.if | |
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 | |
with: | |
fetch-depth: 0 | |
submodules: 'recursive' | |
- name: Setup Go | |
if: matrix.if | |
uses: actions/setup-go@v5 | |
with: | |
go-version: ^1.25.1 | |
- name: Set tag | |
if: matrix.if | |
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 | |
echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV" | |
- name: Checkout main branch | |
if: matrix.if && github.ref == 'refs/heads/main-next' && github.event_name != 'workflow_dispatch' | |
run: |- | |
cd clients/apple | |
git checkout main | |
- name: Checkout dev branch | |
if: matrix.if && github.ref == 'refs/heads/dev-next' | |
run: |- | |
cd clients/apple | |
git checkout dev | |
- name: Setup certificates | |
if: matrix.if | |
run: |- | |
CERTIFICATE_PATH=$RUNNER_TEMP/Certificates.p12 | |
KEYCHAIN_PATH=$RUNNER_TEMP/certificates.keychain-db | |
echo -n "$CERTIFICATES_P12" | base64 --decode -o $CERTIFICATE_PATH | |
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH | |
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH | |
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
security list-keychain -d user -s $KEYCHAIN_PATH | |
PROFILES_ZIP_PATH=$RUNNER_TEMP/Profiles.zip | |
echo -n "$PROVISIONING_PROFILES" | base64 --decode -o $PROFILES_ZIP_PATH | |
PROFILES_PATH="$HOME/Library/MobileDevice/Provisioning Profiles" | |
mkdir -p "$PROFILES_PATH" | |
unzip $PROFILES_ZIP_PATH -d "$PROFILES_PATH" | |
ASC_KEY_PATH=$RUNNER_TEMP/Key.p12 | |
echo -n "$ASC_KEY" | base64 --decode -o $ASC_KEY_PATH | |
xcrun notarytool store-credentials "notarytool-password" \ | |
--key $ASC_KEY_PATH \ | |
--key-id $ASC_KEY_ID \ | |
--issuer $ASC_KEY_ISSUER_ID | |
echo "ASC_KEY_PATH=$ASC_KEY_PATH" >> "$GITHUB_ENV" | |
echo "ASC_KEY_ID=$ASC_KEY_ID" >> "$GITHUB_ENV" | |
echo "ASC_KEY_ISSUER_ID=$ASC_KEY_ISSUER_ID" >> "$GITHUB_ENV" | |
env: | |
CERTIFICATES_P12: ${{ secrets.CERTIFICATES_P12 }} | |
P12_PASSWORD: ${{ secrets.P12_PASSWORD }} | |
KEYCHAIN_PASSWORD: ${{ secrets.P12_PASSWORD }} | |
PROVISIONING_PROFILES: ${{ secrets.PROVISIONING_PROFILES }} | |
ASC_KEY: ${{ secrets.ASC_KEY }} | |
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }} | |
ASC_KEY_ISSUER_ID: ${{ secrets.ASC_KEY_ISSUER_ID }} | |
- name: Build library | |
if: matrix.if | |
run: |- | |
make lib_install | |
export PATH="$PATH:$(go env GOPATH)/bin" | |
go run ./cmd/internal/build_libbox -target apple -platform ${{ matrix.platform }} | |
mv Libbox.xcframework clients/apple | |
- name: Update macOS version | |
if: matrix.if && matrix.name == 'macOS' && github.event_name == 'workflow_dispatch' | |
run: |- | |
MACOS_PROJECT_VERSION=$(go run -v ./cmd/internal/app_store_connect next_macos_project_version) | |
echo "MACOS_PROJECT_VERSION=$MACOS_PROJECT_VERSION" | |
echo "MACOS_PROJECT_VERSION=$MACOS_PROJECT_VERSION" >> "$GITHUB_ENV" | |
- name: Update version | |
if: matrix.if && matrix.name != 'iOS' | |
run: |- | |
go run -v ./cmd/internal/update_apple_version --ci | |
- name: Build | |
if: matrix.if | |
run: |- | |
cd clients/apple | |
xcodebuild archive \ | |
-scheme "${{ matrix.scheme }}" \ | |
-configuration Release \ | |
-destination "${{ matrix.destination }}" \ | |
-archivePath "${{ matrix.archive }}" \ | |
-allowProvisioningUpdates \ | |
-authenticationKeyPath $ASC_KEY_PATH \ | |
-authenticationKeyID $ASC_KEY_ID \ | |
-authenticationKeyIssuerID $ASC_KEY_ISSUER_ID | |
- name: Upload to App Store Connect | |
if: matrix.if && matrix.name != 'macOS-standalone' && github.event_name == 'workflow_dispatch' | |
run: |- | |
go run -v ./cmd/internal/app_store_connect cancel_app_store ${{ matrix.platform }} | |
cd clients/apple | |
xcodebuild -exportArchive \ | |
-archivePath "${{ matrix.archive }}" \ | |
-exportOptionsPlist ${{ matrix.upload }} \ | |
-allowProvisioningUpdates \ | |
-authenticationKeyPath $ASC_KEY_PATH \ | |
-authenticationKeyID $ASC_KEY_ID \ | |
-authenticationKeyIssuerID $ASC_KEY_ISSUER_ID | |
- name: Publish to TestFlight | |
if: matrix.if && matrix.name != 'macOS-standalone' && github.event_name == 'workflow_dispatch' && github.ref =='refs/heads/dev-next' | |
run: |- | |
go run -v ./cmd/internal/app_store_connect publish_testflight ${{ matrix.platform }} | |
- name: Build image | |
if: matrix.if && matrix.name == 'macOS-standalone' && github.event_name == 'workflow_dispatch' | |
run: |- | |
pushd clients/apple | |
xcodebuild -exportArchive \ | |
-archivePath "${{ matrix.archive }}" \ | |
-exportOptionsPlist ${{ matrix.export }} \ | |
-exportPath "${{ matrix.export_path }}" | |
brew install create-dmg | |
create-dmg \ | |
--volname "sing-box" \ | |
--volicon "${{ matrix.export_path }}/SFM.app/Contents/Resources/AppIcon.icns" \ | |
--icon "SFM.app" 0 0 \ | |
--hide-extension "SFM.app" \ | |
--app-drop-link 0 0 \ | |
--skip-jenkins \ | |
SFM.dmg "${{ matrix.export_path }}/SFM.app" | |
xcrun notarytool submit "SFM.dmg" --wait --keychain-profile "notarytool-password" | |
cd "${{ matrix.archive }}" | |
zip -r SFM.dSYMs.zip dSYMs | |
popd | |
mkdir -p dist | |
cp clients/apple/SFM.dmg "dist/SFM-${VERSION}-universal.dmg" | |
cp "clients/apple/${{ matrix.archive }}/SFM.dSYMs.zip" "dist/SFM-${VERSION}-universal.dSYMs.zip" | |
- name: Upload image | |
if: matrix.if && matrix.name == 'macOS-standalone' && github.event_name == 'workflow_dispatch' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: binary-macos-dmg | |
path: 'dist' | |
upload: | |
name: Upload builds | |
if: "!failure() && github.event_name == 'workflow_dispatch' && (inputs.build == 'All' || inputs.build == 'Binary' || inputs.build == 'Android' || inputs.build == 'Apple' || inputs.build == 'macOS-standalone')" | |
runs-on: ubuntu-latest | |
needs: | |
- calculate_version | |
- build | |
- build_android | |
- build_apple | |
steps: | |
- name: Checkout | |
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 | |
with: | |
fetch-depth: 0 | |
- name: Cache ghr | |
uses: actions/cache@v4 | |
id: cache-ghr | |
with: | |
path: | | |
~/go/bin/ghr | |
key: ghr | |
- name: Setup ghr | |
if: steps.cache-ghr.outputs.cache-hit != 'true' | |
run: |- | |
cd $HOME | |
git clone https://github.com/nekohasekai/ghr ghr | |
cd ghr | |
go install -v . | |
- 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 | |
echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV" | |
- name: Download builds | |
uses: actions/download-artifact@v5 | |
with: | |
path: dist | |
merge-multiple: true | |
- name: Upload builds | |
if: ${{ env.PUBLISHED == 'false' }} | |
run: |- | |
export PATH="$PATH:$HOME/go/bin" | |
ghr --replace --draft --prerelease -p 5 "v${VERSION}" dist | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Replace builds | |
if: ${{ env.PUBLISHED != 'false' }} | |
run: |- | |
export PATH="$PATH:$HOME/go/bin" | |
ghr --replace -p 5 "v${VERSION}" dist | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |