fix(website): replace checkmark logo with lightning bolt #30
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
| # ============================================================================ | |
| # UNBOUND — CI/CD Build Pipeline (GitHub Actions) | |
| # ============================================================================ | |
| # Triggers: | |
| # - Push to main/master | |
| # - Pull requests to main/master | |
| # - Manual dispatch (workflow_dispatch) | |
| # - Tags (v*) | |
| # | |
| # Builds: | |
| # - Windows (Wails + Go) | |
| # - Linux (Go native) | |
| # - macOS (Wails + Go) | |
| # - Android (Gradle) | |
| # - OpenWrt (Docker SDK) | |
| # - Steam Deck / Decky Plugin (Node.js) | |
| # - Magisk Module (ZIP) | |
| # | |
| # Artifacts are uploaded per-platform and optionally released on tags. | |
| # ============================================================================ | |
| name: Build & Release | |
| on: | |
| push: | |
| branches: [main, master] | |
| tags: ['v*'] | |
| pull_request: | |
| branches: [main, master] | |
| workflow_dispatch: | |
| inputs: | |
| targets: | |
| description: 'Comma-separated targets (windows,linux,macos,android,openwrt,decky,magisk,all)' | |
| required: false | |
| default: 'all' | |
| release: | |
| description: 'Create a GitHub Release?' | |
| required: false | |
| default: 'false' | |
| type: boolean | |
| env: | |
| GO_VERSION: '1.23' | |
| NODE_VERSION: '20' | |
| JAVA_VERSION: '17' | |
| ANDROID_SDK_VERSION: 34 | |
| # ── Concurrency: cancel in-progress runs on same branch ────────────────────── | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| # Resolve version from wails.json | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| resolve-version: | |
| name: Resolve Version | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - id: version | |
| run: | | |
| VER=$(jq -r '.info.productVersion // "0.0.0-dev"' wails.json 2>/dev/null || echo "0.0.0-dev") | |
| if [[ "${{ github.ref_type }}" == "tag" ]]; then | |
| VER="${{ github.ref_name }}" | |
| VER="${VER#v}" # strip leading 'v' | |
| fi | |
| echo "version=$VER" >> "$GITHUB_OUTPUT" | |
| echo "Resolved version: $VER" | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| # Windows (Wails GUI) | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| build-windows: | |
| name: Windows (Wails) | |
| runs-on: windows-latest | |
| needs: resolve-version | |
| env: | |
| VERSION: ${{ needs.resolve-version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'frontend' | |
| - name: Install Wails CLI | |
| run: go install github.com/wailsapp/wails/v2/cmd/wails@latest | |
| - name: Build | |
| run: | | |
| wails build -clean -o unbound.exe | |
| shell: pwsh | |
| - name: Package release | |
| run: | | |
| $dist = "unbound-v${{ env.VERSION }}-win64" | |
| New-Item -ItemType Directory -Force -Path "release/$dist" | |
| Copy-Item "build\bin\unbound.exe" "release\$dist\" | |
| Copy-Item "README_RELEASE.txt" "release\$dist\README.txt" | |
| Compress-Archive -Path "release\$dist\*" -DestinationPath "release\$dist.zip" -Force | |
| shell: pwsh | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: unbound-windows | |
| path: release/*.zip | |
| retention-days: 30 | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| # Linux (Go CLI/native) | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| build-linux: | |
| name: Linux (Go) | |
| runs-on: ubuntu-latest | |
| needs: resolve-version | |
| env: | |
| VERSION: ${{ needs.resolve-version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'frontend' | |
| - name: Build frontend | |
| run: | | |
| cd frontend | |
| npm ci | |
| npm run build | |
| - name: Build Linux binary | |
| run: | | |
| go build -trimpath -ldflags="-s -w" -o build/bin/unbound-linux ./... | |
| - name: Package release | |
| run: | | |
| mkdir -p release | |
| tar -czf "release/unbound-v${VERSION}-linux-amd64.tar.gz" \ | |
| -C build/bin unbound-linux | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: unbound-linux | |
| path: release/*.tar.gz | |
| retention-days: 30 | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| # macOS (Wails GUI) | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| build-macos: | |
| name: macOS (Wails Universal) | |
| runs-on: macos-latest | |
| needs: resolve-version | |
| env: | |
| VERSION: ${{ needs.resolve-version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'frontend' | |
| - name: Install Wails CLI | |
| run: go install github.com/wailsapp/wails/v2/cmd/wails@latest | |
| - name: Build | |
| run: wails build -platform darwin/universal -clean | |
| - name: Package release | |
| run: | | |
| mkdir -p release | |
| ditto -c -k --sequesterRsrc --keepParent \ | |
| build/bin/Unbound.app \ | |
| "release/unbound-v${VERSION}-macos-universal.zip" | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: unbound-macos | |
| path: release/*.zip | |
| retention-days: 30 | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| # Android (Gradle APK) | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| build-android: | |
| name: Android (Gradle) | |
| runs-on: ubuntu-latest | |
| needs: resolve-version | |
| env: | |
| VERSION: ${{ needs.resolve-version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up JDK | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: ${{ env.JAVA_VERSION }} | |
| - name: Setup Android SDK | |
| uses: android-actions/setup-android@v3 | |
| - name: Accept licenses | |
| run: yes | sdkmanager --licenses || true | |
| - name: Build APK | |
| working-directory: android | |
| run: | | |
| chmod +x ./gradlew 2>/dev/null || true | |
| ./gradlew assembleRelease 2>/dev/null || gradle assembleRelease | |
| - name: Package release | |
| run: | | |
| mkdir -p release | |
| find android -name "*.apk" -exec cp {} release/ \; | |
| cd release | |
| for apk in *.apk; do | |
| mv "$apk" "unbound-v${VERSION}-android-${$apk##*-}" 2>/dev/null || true | |
| done | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: unbound-android | |
| path: release/*.apk | |
| retention-days: 30 | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| # OpenWrt (Docker SDK → IPK) | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| build-openwrt: | |
| name: OpenWrt (Docker IPK) | |
| runs-on: ubuntu-latest | |
| needs: resolve-version | |
| if: ${{ github.event_name != 'pull_request' }} | |
| env: | |
| VERSION: ${{ needs.resolve-version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go (for native binary) | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Cross-compile OpenWrt binary (mipsel) | |
| run: | | |
| GOOS=linux GOARCH=mipsle GOMIPS=softfloat \ | |
| go build -trimpath -ldflags="-s -w" \ | |
| -o build/bin/unbound-openwrt-mipsle ./... | |
| - name: Build IPK via Docker SDK | |
| run: | | |
| if [ -d "openwrt/unbound-wrt" ]; then | |
| docker build \ | |
| --build-arg VERSION=${VERSION} \ | |
| --build-arg ARCH=mipsel_24kc \ | |
| -t unbound-openwrt-builder \ | |
| -f scripts/docker/Dockerfile.openwrt \ | |
| openwrt/unbound-wrt/ || echo "IPK build skipped (SDK not available)" | |
| fi | |
| continue-on-error: true | |
| - name: Package release | |
| run: | | |
| mkdir -p release | |
| if [ -f "build/bin/unbound-openwrt-mipsle" ]; then | |
| tar -czf "release/unbound-v${VERSION}-openwrt-mipsle.tar.gz" \ | |
| -C build/bin unbound-openwrt-mipsle | |
| fi | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: unbound-openwrt | |
| path: release/* | |
| retention-days: 30 | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| # Steam Deck / Decky Loader Plugin | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| build-decky: | |
| name: Decky Plugin (Steam Deck) | |
| runs-on: ubuntu-latest | |
| needs: resolve-version | |
| env: | |
| VERSION: ${{ needs.resolve-version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache-dependency-path: decky-plugin/package-lock.json | |
| - name: Build plugin | |
| working-directory: decky-plugin | |
| run: | | |
| npm ci | |
| npm run build || echo "Build script not defined" | |
| - name: Package release | |
| run: | | |
| mkdir -p release | |
| tar -czf "release/unbound-v${VERSION}-decky-plugin.tar.gz" \ | |
| -C decky-plugin . | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: unbound-decky | |
| path: release/*.tar.gz | |
| retention-days: 30 | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| # Magisk Module | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| build-magisk: | |
| name: Magisk Module | |
| runs-on: ubuntu-latest | |
| needs: resolve-version | |
| env: | |
| VERSION: ${{ needs.resolve-version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Package module | |
| run: | | |
| mkdir -p release | |
| cd magisk-module | |
| zip -r "../release/unbound-v${VERSION}-magisk.zip" . \ | |
| -x "*.git*" -x "*.DS_Store" | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: unbound-magisk | |
| path: release/*.zip | |
| retention-days: 30 | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| # Create GitHub Release (on tag or manual dispatch) | |
| # ─────────────────────────────────────────────────────────────────────────── | |
| release: | |
| name: Create GitHub Release | |
| runs-on: ubuntu-latest | |
| needs: | |
| - resolve-version | |
| - build-windows | |
| - build-linux | |
| - build-macos | |
| - build-android | |
| - build-openwrt | |
| - build-decky | |
| - build-magisk | |
| if: >- | |
| always() && | |
| (github.ref_type == 'tag' || | |
| (github.event_name == 'workflow_dispatch' && | |
| github.event.inputs.release == 'true')) | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts/ | |
| - name: List artifacts | |
| run: | | |
| echo "Downloaded artifacts:" | |
| find artifacts/ -type f | head -50 | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_type == 'tag' && github.ref_name || format('v{0}', needs.resolve-version.outputs.version) }} | |
| name: "Unbound v${{ needs.resolve-version.outputs.version }}" | |
| body: | | |
| ## 🚀 Unbound v${{ needs.resolve-version.outputs.version }}: Глобальное обновление | |
| Это **мажорный релиз**, который превращает Unbound из одного десктопного приложения в **полную мультиплатформенную экосистему** для обхода DPI-цензуры. | |
| ### ✨ Что нового | |
| - **🌍 Мультиплатформенная экосистема** — Desktop, Android, iOS, Linux, OpenWrt, расширения для браузеров | |
| - **🎯 Автоподбор V2** — Параллельный сканер, находящий оптимальные профили за секунды | |
| - **🔄 Интеграция с системным треем** — Работает в фоне, управляется из трея | |
| - **🎨 Обновлённый интерфейс** — Современный дизайн с мониторингом в реальном времени | |
| - **⚡ Улучшенная производительность** — Строгий таймаут 5 секунд на зонд, никаких зависаний | |
| - **🔒 Повышенная безопасность** — HideWindow на всех дочерних процессах, никаких мигающих окон | |
| ### 📦 Поддерживаемые платформы | |
| | Платформа | Формат | Статус | | |
| |-----------|--------|--------| | |
| | **Desktop (Windows/macOS)** | Нативное приложение | ✅ Готово | | |
| | **Android** | APK | ✅ Готово | | |
| | **Linux** | CLI-бинарник | ✅ Готово | | |
| | **OpenWrt** | IPK пакет | ✅ Готово | | |
| | **Браузер** | Расширение | ✅ Готово | | |
| | **Steam Deck** | Decky плагин | ✅ Готово | | |
| | **Magisk** | ZIP-модуль | ✅ Готово | | |
| ### 🐛 Исправления | |
| - Исправлено сохранение настроек | |
| - Исправлено поведение при закрытии окна (сворачивается в трей) | |
| - Исправлено зависание Автоподбора | |
| - Убрано мигание консоли | |
| --- | |
| 📖 [Установка](README.md) • [Документация](docs/BUILDING.md) • [Исходный код](https://github.com/bobberdolle1/unbound) | |
| files: | | |
| artifacts/**/*.zip | |
| artifacts/**/*.tar.gz | |
| artifacts/**/*.apk | |
| artifacts/**/*.exe | |
| artifacts/**/*.ipk | |
| draft: ${{ github.ref_type != 'tag' }} | |
| prerelease: ${{ contains(needs.resolve-version.outputs.version, 'dev') || contains(needs.resolve-version.outputs.version, 'beta') }} | |
| generate_release_notes: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |