馃敄 chore(release): Bump version to v0.5.6 #48
Workflow file for this run
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: Release | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| env: | |
| SING_BOX_VERSION: "1.13.13" | |
| jobs: | |
| build: | |
| name: Build ${{ matrix.asset }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| binary: v2raydar.exe | |
| asset: v2raydar-windows-x86_64.exe | |
| embedded_asset: v2raydar-windows-x86_64_with_singbox.zip | |
| embedded_format: zip | |
| embedded_binary: v2raydar.exe | |
| sing_box_platform: windows | |
| sing_box_arch: amd64 | |
| sing_box_binary: sing-box.exe | |
| - os: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| binary: v2raydar | |
| asset: v2raydar-linux-x86_64 | |
| embedded_asset: v2raydar-linux-x86_64_with_singbox.tar.gz | |
| embedded_format: tar.gz | |
| embedded_binary: v2raydar | |
| sing_box_platform: linux | |
| sing_box_arch: amd64 | |
| sing_box_binary: sing-box | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Cache Cargo build state | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target/${{ matrix.target }} | |
| key: cargo-build-${{ runner.os }}-${{ matrix.target }}-${{ hashFiles('Cargo.lock') }} | |
| restore-keys: | | |
| cargo-build-${{ runner.os }}-${{ matrix.target }}- | |
| - name: Install Rust target | |
| shell: bash | |
| run: | | |
| rustup default stable | |
| rustup target add "${{ matrix.target }}" | |
| - name: Build release binary | |
| run: cargo build --release --locked --target "${{ matrix.target }}" | |
| - name: Stage executable | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Force dist | Out-Null | |
| $source = Join-Path "target/${{ matrix.target }}/release" "${{ matrix.binary }}" | |
| $destination = Join-Path "dist" "${{ matrix.asset }}" | |
| Copy-Item -LiteralPath $source -Destination $destination | |
| - name: Upload executable artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.asset }} | |
| path: dist/${{ matrix.asset }} | |
| if-no-files-found: error | |
| - name: Stage embedded sing-box package | |
| shell: pwsh | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| $headers = @{ "User-Agent" = "github-actions" } | |
| # Inject the token into the headers if it exists | |
| if ([bool]$env:GITHUB_TOKEN) { | |
| $headers["Authorization"] = "Bearer $($env:GITHUB_TOKEN)" | |
| } | |
| $version = "${{ env.SING_BOX_VERSION }}" | |
| $release = Invoke-RestMethod -Headers $headers -Uri "https://api.github.com/repos/SagerNet/sing-box/releases/tags/v$version" | |
| function Test-NameToken([string]$Name, [string]$Token) { | |
| return $Name -match ('(^|[-_.])' + [regex]::Escape($Token) + '($|[-_.])') | |
| } | |
| $asset = $release.assets | | |
| Where-Object { | |
| $name = $_.name.ToLowerInvariant() | |
| $name -like "*${{ matrix.sing_box_platform }}*" -and | |
| (Test-NameToken $name "${{ matrix.sing_box_arch }}") -and | |
| ($name.EndsWith(".zip") -or $name.EndsWith(".tar.gz") -or $name.EndsWith(".tgz")) | |
| } | | |
| Select-Object -First 1 | |
| if (-not $asset) { | |
| throw "No sing-box v$version asset found for ${{ matrix.sing_box_platform }}-${{ matrix.sing_box_arch }}" | |
| } | |
| $download = Join-Path "dist" $asset.name | |
| Invoke-WebRequest -Headers $headers -Uri $asset.browser_download_url -OutFile $download | |
| $extractRoot = Join-Path "dist" "sing-box-$version-${{ matrix.sing_box_platform }}-${{ matrix.sing_box_arch }}" | |
| New-Item -ItemType Directory -Force $extractRoot | Out-Null | |
| if ($asset.name.ToLowerInvariant().EndsWith(".zip")) { | |
| Expand-Archive -LiteralPath $download -DestinationPath $extractRoot -Force | |
| } else { | |
| tar -xf $download -C $extractRoot | |
| } | |
| $singBox = Get-ChildItem -LiteralPath $extractRoot -Recurse -File -Filter "${{ matrix.sing_box_binary }}" | | |
| Select-Object -First 1 | |
| if (-not $singBox) { | |
| throw "sing-box executable was not found after extracting $($asset.name)" | |
| } | |
| & $singBox.FullName version | |
| $packageRoot = Join-Path "dist" "package-${{ matrix.embedded_asset }}" | |
| New-Item -ItemType Directory -Force $packageRoot | Out-Null | |
| Copy-Item -LiteralPath (Join-Path "dist" "${{ matrix.asset }}") -Destination (Join-Path $packageRoot "${{ matrix.embedded_binary }}") | |
| Copy-Item -LiteralPath $singBox.FullName -Destination (Join-Path $packageRoot "${{ matrix.sing_box_binary }}") | |
| if ("${{ runner.os }}" -ne "Windows") { | |
| chmod +x (Join-Path $packageRoot "${{ matrix.embedded_binary }}") | |
| chmod +x (Join-Path $packageRoot "${{ matrix.sing_box_binary }}") | |
| } | |
| if ("${{ matrix.embedded_format }}" -eq "zip") { | |
| Compress-Archive -Path (Join-Path $packageRoot "*") -DestinationPath (Join-Path "dist" "${{ matrix.embedded_asset }}") -Force | |
| } else { | |
| tar -C $packageRoot -czf (Join-Path "dist" "${{ matrix.embedded_asset }}") . | |
| } | |
| - name: Upload embedded sing-box artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.embedded_asset }} | |
| path: dist/${{ matrix.embedded_asset }} | |
| if-no-files-found: error | |
| build-macos: | |
| name: Build v2raydar-macos-universal.app.zip | |
| runs-on: macos-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Cache Cargo build state | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target/x86_64-apple-darwin | |
| target/aarch64-apple-darwin | |
| key: cargo-build-${{ runner.os }}-macos-universal-${{ hashFiles('Cargo.lock') }} | |
| restore-keys: | | |
| cargo-build-${{ runner.os }}-macos-universal- | |
| - name: Install Rust targets | |
| shell: bash | |
| run: | | |
| rustup default stable | |
| rustup target add x86_64-apple-darwin aarch64-apple-darwin | |
| - name: Build release binaries | |
| shell: bash | |
| run: | | |
| cargo build --release --locked --target x86_64-apple-darwin | |
| cargo build --release --locked --target aarch64-apple-darwin | |
| - name: Stage universal app bundle | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| asset="v2raydar-macos-universal.app.zip" | |
| app="dist/V2RayDAR.app" | |
| version="$(awk -F '"' '/^version = / { print $2; exit }' Cargo.toml)" | |
| mkdir -p "$app/Contents/MacOS" "$app/Contents/Resources" | |
| lipo -create \ | |
| -output "$app/Contents/MacOS/v2raydar-bin" \ | |
| "target/x86_64-apple-darwin/release/v2raydar" \ | |
| "target/aarch64-apple-darwin/release/v2raydar" | |
| chmod +x "$app/Contents/MacOS/v2raydar-bin" | |
| lipo -info "$app/Contents/MacOS/v2raydar-bin" | |
| cat > "$app/Contents/MacOS/V2RayDAR" <<'EOF' | |
| #!/bin/sh | |
| set -eu | |
| dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" | |
| app="$dir/v2raydar-bin" | |
| if [ -t 1 ]; then | |
| exec "$app" "$@" | |
| fi | |
| APP_PATH="$app" osascript <<'APPLESCRIPT' | |
| set appPath to system attribute "APP_PATH" | |
| tell application "Terminal" | |
| activate | |
| do script quoted form of appPath | |
| end tell | |
| APPLESCRIPT | |
| EOF | |
| chmod +x "$app/Contents/MacOS/V2RayDAR" | |
| cat > "$app/Contents/Info.plist" <<EOF | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| <plist version="1.0"> | |
| <dict> | |
| <key>CFBundleDevelopmentRegion</key> | |
| <string>en</string> | |
| <key>CFBundleExecutable</key> | |
| <string>V2RayDAR</string> | |
| <key>CFBundleIconFile</key> | |
| <string>V2RayDAR</string> | |
| <key>CFBundleIdentifier</key> | |
| <string>app.v2raydar.V2RayDAR</string> | |
| <key>CFBundleInfoDictionaryVersion</key> | |
| <string>6.0</string> | |
| <key>CFBundleName</key> | |
| <string>V2RayDAR</string> | |
| <key>CFBundlePackageType</key> | |
| <string>APPL</string> | |
| <key>CFBundleShortVersionString</key> | |
| <string>${version}</string> | |
| <key>CFBundleVersion</key> | |
| <string>${GITHUB_RUN_NUMBER}</string> | |
| <key>LSMinimumSystemVersion</key> | |
| <string>10.13</string> | |
| <key>NSHighResolutionCapable</key> | |
| <true/> | |
| </dict> | |
| </plist> | |
| EOF | |
| iconset="dist/V2RayDAR.iconset" | |
| mkdir -p "$iconset" | |
| sips -z 16 16 "assets/V2RayDAR_logo_v1.png" --out "$iconset/icon_16x16.png" >/dev/null | |
| sips -z 32 32 "assets/V2RayDAR_logo_v1.png" --out "$iconset/icon_16x16@2x.png" >/dev/null | |
| sips -z 32 32 "assets/V2RayDAR_logo_v1.png" --out "$iconset/icon_32x32.png" >/dev/null | |
| sips -z 64 64 "assets/V2RayDAR_logo_v1.png" --out "$iconset/icon_32x32@2x.png" >/dev/null | |
| sips -z 128 128 "assets/V2RayDAR_logo_v1.png" --out "$iconset/icon_128x128.png" >/dev/null | |
| sips -z 256 256 "assets/V2RayDAR_logo_v1.png" --out "$iconset/icon_128x128@2x.png" >/dev/null | |
| sips -z 256 256 "assets/V2RayDAR_logo_v1.png" --out "$iconset/icon_256x256.png" >/dev/null | |
| sips -z 512 512 "assets/V2RayDAR_logo_v1.png" --out "$iconset/icon_256x256@2x.png" >/dev/null | |
| sips -z 512 512 "assets/V2RayDAR_logo_v1.png" --out "$iconset/icon_512x512.png" >/dev/null | |
| sips -z 1024 1024 "assets/V2RayDAR_logo_v1.png" --out "$iconset/icon_512x512@2x.png" >/dev/null | |
| iconutil -c icns "$iconset" -o "$app/Contents/Resources/V2RayDAR.icns" | |
| ditto -c -k --sequesterRsrc --keepParent "$app" "dist/$asset" | |
| - name: Upload app artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: v2raydar-macos-universal.app.zip | |
| path: dist/v2raydar-macos-universal.app.zip | |
| if-no-files-found: error | |
| - name: Stage embedded sing-box app bundle | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| version="${SING_BOX_VERSION}" | |
| embedded_asset="v2raydar-macos-universal_with_singbox.zip" | |
| work="dist/sing-box-${version}-darwin" | |
| mkdir -p "$work" | |
| python3 <<'PY' | |
| import json | |
| import os | |
| import re | |
| import urllib.request | |
| version = os.environ["SING_BOX_VERSION"] | |
| github_token = os.environ.get("GITHUB_TOKEN") | |
| work = os.path.join("dist", f"sing-box-{version}-darwin") | |
| url = f"https://api.github.com/repos/SagerNet/sing-box/releases/tags/v{version}" | |
| headers = {"User-Agent": "github-actions"} | |
| # Inject the token into the headers if it exists | |
| if github_token: | |
| headers["Authorization"] = f"Bearer {github_token}" | |
| req = urllib.request.Request(url, headers=headers) | |
| release = json.load(urllib.request.urlopen(req)) | |
| def token(name, value): | |
| return re.search(r"(^|[-_.])" + re.escape(value) + r"($|[-_.])", name) is not None | |
| for arch in ("amd64", "arm64"): | |
| for asset in release.get("assets", []): | |
| name = asset["name"].lower() | |
| if "darwin" in name and token(name, arch) and name.endswith((".tar.gz", ".tgz", ".zip")): | |
| target = os.path.join(work, asset["name"]) | |
| # Create a request object for the download to pass headers here too | |
| download_req = urllib.request.Request(asset["browser_download_url"], headers=headers) | |
| with urllib.request.urlopen(download_req) as response, open(target, 'wb') as out_file: | |
| out_file.write(response.read()) | |
| break | |
| else: | |
| raise SystemExit(f"No sing-box v{version} darwin-{arch} asset found") | |
| PY | |
| for archive in "$work"/*; do | |
| mkdir -p "$work/extract/$(basename "$archive")" | |
| case "$archive" in | |
| *.zip) unzip -q "$archive" -d "$work/extract/$(basename "$archive")" ;; | |
| *) tar -xf "$archive" -C "$work/extract/$(basename "$archive")" ;; | |
| esac | |
| done | |
| amd64_bin="$(find "$work/extract" -path '*darwin-amd64*' -type f -name sing-box | head -n 1)" | |
| arm64_bin="$(find "$work/extract" -path '*darwin-arm64*' -type f -name sing-box | head -n 1)" | |
| test -n "$amd64_bin" | |
| test -n "$arm64_bin" | |
| lipo -create -output "dist/V2RayDAR.app/Contents/MacOS/sing-box" "$amd64_bin" "$arm64_bin" | |
| chmod +x "dist/V2RayDAR.app/Contents/MacOS/sing-box" | |
| "dist/V2RayDAR.app/Contents/MacOS/sing-box" version | |
| ditto -c -k --sequesterRsrc --keepParent "dist/V2RayDAR.app" "dist/$embedded_asset" | |
| - name: Upload embedded sing-box app artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: v2raydar-macos-universal_with_singbox.zip | |
| path: dist/v2raydar-macos-universal_with_singbox.zip | |
| if-no-files-found: error | |
| build-termux: | |
| name: Build ${{ matrix.asset }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - target: aarch64-linux-android | |
| clang_prefix: aarch64-linux-android | |
| asset: v2raydar-termux-aarch64.tar.gz | |
| package_dir: v2raydar-termux-aarch64 | |
| label: aarch64 | |
| - target: x86_64-linux-android | |
| clang_prefix: x86_64-linux-android | |
| asset: v2raydar-termux-x86_64.tar.gz | |
| package_dir: v2raydar-termux-x86_64 | |
| label: x86_64 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Cache Cargo build state | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target/${{ matrix.target }} | |
| key: cargo-build-${{ runner.os }}-${{ matrix.target }}-${{ hashFiles('Cargo.lock') }} | |
| restore-keys: | | |
| cargo-build-${{ runner.os }}-${{ matrix.target }}- | |
| - name: Install Rust target | |
| shell: bash | |
| run: | | |
| rustup default stable | |
| rustup target add "${{ matrix.target }}" | |
| - name: Build release binary | |
| shell: bash | |
| env: | |
| API_LEVEL: "24" | |
| run: | | |
| set -euo pipefail | |
| ndk="${ANDROID_NDK_HOME:-${ANDROID_NDK_LATEST_HOME:-}}" | |
| if [ -z "$ndk" ]; then | |
| echo "ANDROID_NDK_HOME or ANDROID_NDK_LATEST_HOME is required" >&2 | |
| exit 1 | |
| fi | |
| linker="${ndk}/toolchains/llvm/prebuilt/linux-x86_64/bin/${{ matrix.clang_prefix }}${API_LEVEL}-clang" | |
| ar="${ndk}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" | |
| test -x "$linker" | |
| test -x "$ar" | |
| linker_var="CARGO_TARGET_$(echo "${{ matrix.target }}" | tr '[:lower:]-' '[:upper:]_')_LINKER" | |
| cc_var="CC_$(echo "${{ matrix.target }}" | tr '-' '_')" | |
| ar_var="AR_$(echo "${{ matrix.target }}" | tr '-' '_')" | |
| export "$linker_var=$linker" | |
| export "$cc_var=$linker" | |
| export "$ar_var=$ar" | |
| cargo build --release --locked --target "${{ matrix.target }}" | |
| - name: Stage Termux package | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| asset="${{ matrix.asset }}" | |
| package="dist/${{ matrix.package_dir }}" | |
| mkdir -p "$package" | |
| cp target/${{ matrix.target }}/release/v2raydar "$package/v2raydar" | |
| chmod +x "$package/v2raydar" | |
| cat > "$package/install-termux.sh" <<EOF | |
| #!/data/data/com.termux/files/usr/bin/bash | |
| cd "\$(dirname "\$0")" | |
| echo "Installing sing-box..." | |
| if ! pkg install -y sing-box=${SING_BOX_VERSION}; then | |
| echo "鈿狅笍 sing-box=${SING_BOX_VERSION} not available, trying latest..." | |
| pkg install -y sing-box || echo "鈿狅笍 Install sing-box manually later: pkg install sing-box" | |
| fi | |
| install -Dm755 v2raydar "\${PREFIX}/bin/v2raydar" | |
| cat <<'MSG' | |
| Installed V2RayDAR to \$PREFIX/bin/v2raydar. | |
| Run with: v2raydar --no-tui | |
| MSG | |
| EOF | |
| chmod +x "$package/install-termux.sh" | |
| cat > "$package/README-termux.txt" <<EOF | |
| V2RayDAR Termux ${{ matrix.label }} release | |
| This package is built for ${{ matrix.label }} Android devices running Termux. | |
| It does not include sing-box. Install the pinned Termux package: | |
| pkg install sing-box=${SING_BOX_VERSION} | |
| Quick install: | |
| tar -xzf ${asset} | |
| cd ${{ matrix.package_dir }} | |
| ./install-termux.sh | |
| v2raydar --no-tui | |
| EOF | |
| tar -C dist -czf "dist/$asset" "${{ matrix.package_dir }}" | |
| - name: Upload Termux artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.asset }} | |
| path: dist/${{ matrix.asset }} | |
| if-no-files-found: error | |
| test: | |
| name: Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Cache Cargo test state | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: cargo-test-${{ runner.os }}-${{ hashFiles('Cargo.lock') }} | |
| restore-keys: | | |
| cargo-test-${{ runner.os }}- | |
| - name: Install Rust | |
| shell: bash | |
| run: | | |
| rustup default stable | |
| rustup component add rustfmt clippy | |
| - name: Format check | |
| run: cargo fmt --check | |
| - name: Clippy | |
| run: cargo clippy --locked --all-targets --all-features -- -D warnings | |
| - name: Tests | |
| run: cargo test --locked | |
| publish: | |
| name: Publish GitHub release | |
| needs: [build, build-macos, build-termux, test] | |
| runs-on: ubuntu-latest | |
| if: startsWith(github.ref, 'refs/tags/') | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| TAG_NAME: ${{ github.ref_name }} | |
| REPOSITORY: ${{ github.repository }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Download executable artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: dist | |
| merge-multiple: true | |
| - name: Generate SHA-256 checksums | |
| shell: pwsh | |
| run: | | |
| $lines = Get-ChildItem -LiteralPath dist -File | | |
| Sort-Object Name | | |
| ForEach-Object { | |
| $hash = (Get-FileHash -Algorithm SHA256 -LiteralPath $_.FullName).Hash.ToLowerInvariant() | |
| "$hash $($_.Name)" | |
| } | |
| $lines | Set-Content -LiteralPath "dist/checksums.txt" -Encoding ascii | |
| - name: Create or update release | |
| shell: bash | |
| run: | | |
| git log -1 --format=%b > release-notes.txt | |
| if gh release view "$TAG_NAME" --repo "$REPOSITORY" >/dev/null 2>&1; then | |
| gh release edit "$TAG_NAME" --repo "$REPOSITORY" --notes-file release-notes.txt | |
| gh release upload "$TAG_NAME" dist/* --clobber --repo "$REPOSITORY" | |
| else | |
| gh release create "$TAG_NAME" dist/* \ | |
| --repo "$REPOSITORY" \ | |
| --title "V2RayDAR $TAG_NAME" \ | |
| --notes-file release-notes.txt | |
| fi |