mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-29 21:02:09 +02:00
feat(backend): migrate production backend to Rust
Replace the Go backend with the Rust workspace and route Android/iOS through UniFFI bindings. Include the migrated extension runtime, network, providers, media metadata, downloads and library operations, with version 5.0.0+147. Remove Go sources, adapters, native build selection and CI dependencies. Build Rust unconditionally and lock the iOS Rust pod using a relative path. Retain legacy source and migration evidence in a local ignored archive. Validation: Android Kotlin compile and 53 native tests; Swift Rust-branch equivalence and syntax; CocoaPods install; workflow, shell, Ruby, plist and diff checks. Reuse the preceding 100 Rust tests, fmt/Clippy and five-ABI build checkpoint; no new APK or iOS application build for this cleanup. Known follow-up: URL/URLSearchParams globals are missing from the Rust JS runtime. A controlled extension replay confirms a URL-resolution regression; this commit does not fix that runtime gap.
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
- [ ] `dart format --output=none --set-exit-if-changed lib test`
|
||||
- [ ] `flutter analyze`
|
||||
- [ ] `flutter test`
|
||||
- [ ] `gofmt`, `go vet ./...`, and `go test ./...` in `go_backend/`
|
||||
- [ ] `bash scripts/check_rust_backend.sh`
|
||||
- [ ] Android or iOS native checks
|
||||
- [ ] Manual reproduction or device test
|
||||
|
||||
|
||||
+112
-50
@@ -18,8 +18,9 @@ jobs:
|
||||
pull-requests: read
|
||||
outputs:
|
||||
dart: ${{ steps.filter.outputs.dart }}
|
||||
go: ${{ steps.filter.outputs.go }}
|
||||
android: ${{ steps.filter.outputs.android }}
|
||||
ios: ${{ steps.filter.outputs.ios }}
|
||||
rust: ${{ steps.filter.outputs.rust }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
@@ -40,20 +41,34 @@ jobs:
|
||||
- 'l10n.yaml'
|
||||
- '.fvmrc'
|
||||
- '.github/workflows/ci.yml'
|
||||
go:
|
||||
- 'go_backend/**'
|
||||
- 'android/app/src/test/resources/**'
|
||||
rust:
|
||||
- 'rust_backend/**'
|
||||
- 'scripts/*rust*.sh'
|
||||
- 'android/gradlew'
|
||||
- 'android/gradle/wrapper/**'
|
||||
- '.github/workflows/ci.yml'
|
||||
ios:
|
||||
- 'ios/**'
|
||||
- 'scripts/build_ios.sh'
|
||||
- 'scripts/check_backend_ios.py'
|
||||
- 'lib/**'
|
||||
- 'assets/**'
|
||||
- 'pubspec.yaml'
|
||||
- 'pubspec.lock'
|
||||
- 'l10n.yaml'
|
||||
- '.fvmrc'
|
||||
- '.github/workflows/ci.yml'
|
||||
android:
|
||||
- 'android/**'
|
||||
- 'go_backend/**'
|
||||
- 'lib/models/settings.dart'
|
||||
- 'lib/providers/download_queue_provider*.dart'
|
||||
- 'lib/services/download_request_payload.dart'
|
||||
- 'lib/services/history_database.dart'
|
||||
- 'lib/services/platform_bridge.dart'
|
||||
- 'rust_backend/**'
|
||||
- 'scripts/build_android.sh'
|
||||
- 'scripts/build_rust_backend.sh'
|
||||
- 'scripts/check_backend_apk.py'
|
||||
- 'lib/**'
|
||||
- 'assets/**'
|
||||
- 'pubspec.yaml'
|
||||
- 'pubspec.lock'
|
||||
- 'l10n.yaml'
|
||||
- '.fvmrc'
|
||||
- '.github/workflows/ci.yml'
|
||||
|
||||
@@ -87,40 +102,88 @@ jobs:
|
||||
- name: Analyze
|
||||
run: flutter analyze
|
||||
|
||||
- name: Install media test tools
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ffmpeg
|
||||
ffmpeg -version
|
||||
ffprobe -version
|
||||
|
||||
- name: Run tests
|
||||
run: flutter test
|
||||
|
||||
go:
|
||||
name: Go vet & test
|
||||
rust:
|
||||
name: Rust checks & Android libraries
|
||||
runs-on: ubuntu-latest
|
||||
needs: changes
|
||||
if: needs.changes.outputs.go == 'true'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: go_backend
|
||||
if: needs.changes.outputs.rust == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
|
||||
- name: Setup Java for Android SDK tools
|
||||
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
|
||||
with:
|
||||
go-version-file: go_backend/go.mod
|
||||
cache-dependency-path: go_backend/go.sum
|
||||
distribution: "temurin"
|
||||
java-version: "25"
|
||||
|
||||
- name: Check formatting
|
||||
run: test -z "$(gofmt -l .)"
|
||||
- name: Activate pinned Rust toolchain
|
||||
working-directory: rust_backend
|
||||
run: rustup show
|
||||
|
||||
- name: Vet
|
||||
run: go vet ./...
|
||||
- name: Install C binding generator dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libclang-dev
|
||||
|
||||
- name: Run tests
|
||||
run: go test ./...
|
||||
- name: Rust formatting, Clippy and unit tests
|
||||
run: bash scripts/check_rust_backend.sh
|
||||
|
||||
- name: Install Android NDK
|
||||
run: $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "ndk;29.0.14206865"
|
||||
|
||||
- name: Build Android ARM32 and ARM64 libraries
|
||||
run: ANDROID_NDK_HOME="$ANDROID_HOME/ndk/29.0.14206865" bash scripts/build_rust_backend.sh android
|
||||
|
||||
rust-ios:
|
||||
name: Rust iOS libraries & release application
|
||||
runs-on: macos-latest
|
||||
needs: changes
|
||||
if: needs.changes.outputs.rust == 'true' || needs.changes.outputs.ios == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
|
||||
- name: Activate pinned Rust toolchain
|
||||
working-directory: rust_backend
|
||||
run: rustup show
|
||||
|
||||
- name: Build iOS device and universal simulator XCFramework
|
||||
run: bash scripts/build_rust_backend.sh ios
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version-file: .fvmrc
|
||||
cache: true
|
||||
|
||||
- name: Configure Rust application pods
|
||||
run: |
|
||||
flutter pub get
|
||||
cd ios
|
||||
pod install
|
||||
|
||||
- name: Build and audit Rust iOS release application
|
||||
run: |
|
||||
flutter build ios --release --no-codesign --target lib/main.dart
|
||||
python3 scripts/check_backend_ios.py build/ios/iphoneos/Runner.app \
|
||||
--backend rust --archs arm64 --platform ios --release
|
||||
|
||||
android:
|
||||
name: Android compile & native tests
|
||||
name: Android Rust builds & native tests
|
||||
runs-on: ubuntu-latest
|
||||
needs: changes
|
||||
if: needs.changes.outputs.android == 'true'
|
||||
@@ -135,12 +198,6 @@ jobs:
|
||||
distribution: "temurin"
|
||||
java-version: "25"
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
|
||||
with:
|
||||
go-version-file: go_backend/go.mod
|
||||
cache-dependency-path: go_backend/go.sum
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
|
||||
with:
|
||||
@@ -162,25 +219,30 @@ jobs:
|
||||
"build-tools;37.0.0"
|
||||
echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/29.0.14206865" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build Go backend for Android
|
||||
working-directory: go_backend
|
||||
run: |
|
||||
go install golang.org/x/mobile/cmd/gomobile
|
||||
gomobile init
|
||||
mkdir -p ../android/app/libs
|
||||
gomobile bind \
|
||||
-target=android/arm,android/arm64 \
|
||||
-androidapi 24 \
|
||||
-o ../android/app/libs/gobackend.aar \
|
||||
.
|
||||
env:
|
||||
CGO_ENABLED: 1
|
||||
|
||||
- name: Get Flutter dependencies
|
||||
run: flutter pub get
|
||||
|
||||
- name: Configure Flutter SDK for Gradle
|
||||
run: echo "flutter.sdk=$FLUTTER_ROOT" > android/local.properties
|
||||
|
||||
- name: Compile Kotlin and run native unit tests
|
||||
run: gradle -p android :app:compileDebugKotlin :app:testDebugUnitTest
|
||||
- name: Install Rust application build prerequisites
|
||||
run: |
|
||||
cd rust_backend
|
||||
rustup show
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libclang-dev
|
||||
|
||||
- name: Package Rust application and run native unit tests
|
||||
run: gradle -p android :app:assembleDebug :app:testDebugUnitTest
|
||||
|
||||
- name: Build Rust release application
|
||||
run: bash scripts/build_android.sh --target lib/main.dart
|
||||
|
||||
- name: Verify Rust release APK payloads
|
||||
run: |
|
||||
python3 scripts/check_backend_apk.py \
|
||||
build/app/outputs/flutter-apk/app-arm64-v8a-release.apk \
|
||||
--backend rust --abis arm64-v8a
|
||||
python3 scripts/check_backend_apk.py \
|
||||
build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk \
|
||||
--backend rust --abis armeabi-v7a
|
||||
|
||||
@@ -74,11 +74,14 @@ jobs:
|
||||
distribution: "temurin"
|
||||
java-version: "25"
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
|
||||
with:
|
||||
go-version-file: go_backend/go.mod
|
||||
cache-dependency-path: go_backend/go.sum
|
||||
- name: Activate pinned Rust toolchain
|
||||
working-directory: rust_backend
|
||||
run: rustup show
|
||||
|
||||
- name: Install Rust binding generator dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libclang-dev
|
||||
|
||||
# Cache Gradle for faster builds
|
||||
- name: Cache Gradle
|
||||
@@ -112,26 +115,6 @@ jobs:
|
||||
# Set NDK path
|
||||
echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/29.0.14206865" >> $GITHUB_ENV
|
||||
|
||||
- name: Install gomobile
|
||||
working-directory: go_backend
|
||||
run: |
|
||||
# Installed from inside the module so the go.mod-pinned x/mobile
|
||||
# version is used (reproducible + covered by the setup-go cache).
|
||||
go install golang.org/x/mobile/cmd/gomobile
|
||||
gomobile init
|
||||
|
||||
- name: Build Go backend for Android
|
||||
working-directory: go_backend
|
||||
run: |
|
||||
mkdir -p ../android/app/libs
|
||||
# arm/arm64 only: ndk.abiFilters in app/build.gradle.kts strips
|
||||
# every other ABI from all outputs (universal APK included), so an
|
||||
# amd64 slice would never reach a shipped APK — it only bloats the
|
||||
# aar and slows this step.
|
||||
gomobile bind -target=android/arm,android/arm64 -androidapi 24 -o ../android/app/libs/gobackend.aar .
|
||||
env:
|
||||
CGO_ENABLED: 1
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
|
||||
with:
|
||||
@@ -154,7 +137,7 @@ jobs:
|
||||
|
||||
- name: Build APK (Release - unsigned)
|
||||
run: |
|
||||
bash scripts/build_android.sh
|
||||
bash scripts/build_android.sh --target lib/main.dart
|
||||
ls -la build/app/outputs/flutter-apk/
|
||||
|
||||
- name: Sign APKs
|
||||
@@ -167,7 +150,7 @@ jobs:
|
||||
keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }}
|
||||
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
||||
env:
|
||||
BUILD_TOOLS_VERSION: "36.0.0"
|
||||
BUILD_TOOLS_VERSION: "37.0.0"
|
||||
|
||||
- name: Rename APKs
|
||||
env:
|
||||
@@ -209,6 +192,20 @@ jobs:
|
||||
done
|
||||
ls -la
|
||||
|
||||
- name: Audit signed Rust APKs before upload
|
||||
env:
|
||||
VERSION: ${{ needs.get-version.outputs.version }}
|
||||
run: |
|
||||
apk_dir=build/app/outputs/flutter-apk
|
||||
python3 scripts/check_backend_apk.py "$apk_dir/SpotiFLAC-${VERSION}-arm64.apk" \
|
||||
--backend rust --abis arm64-v8a
|
||||
python3 scripts/check_backend_apk.py "$apk_dir/SpotiFLAC-${VERSION}-arm32.apk" \
|
||||
--backend rust --abis armeabi-v7a
|
||||
for abi in arm64 arm32; do
|
||||
"$ANDROID_HOME/build-tools/37.0.0/zipalign" -c -P 16 4 \
|
||||
"$apk_dir/SpotiFLAC-${VERSION}-${abi}.apk"
|
||||
done
|
||||
|
||||
- name: Upload APK artifact
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
@@ -228,24 +225,16 @@ jobs:
|
||||
sudo xcode-select -s /Applications/Xcode_26.1.1.app
|
||||
xcodebuild -version
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
|
||||
with:
|
||||
go-version-file: go_backend/go.mod
|
||||
cache-dependency-path: go_backend/go.sum
|
||||
- name: Build Rust backend for iOS
|
||||
run: bash scripts/build_ios.sh
|
||||
|
||||
# Cache CocoaPods
|
||||
- name: Cache CocoaPods
|
||||
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
|
||||
with:
|
||||
path: ios/Pods
|
||||
key: pods-${{ runner.os }}-${{ hashFiles('ios/Podfile.lock') }}
|
||||
restore-keys: pods-${{ runner.os }}-
|
||||
|
||||
- name: Build Go backend for iOS
|
||||
run: bash scripts/build_ios.sh
|
||||
env:
|
||||
CGO_ENABLED: 1
|
||||
key: pods-rust-${{ runner.os }}-${{ hashFiles('ios/Podfile', 'ios/Podfile.lock', 'rust_backend/SpotiFLACBackend.podspec', 'rust_backend/Cargo.lock') }}
|
||||
restore-keys: pods-rust-${{ runner.os }}-
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
|
||||
@@ -276,10 +265,14 @@ jobs:
|
||||
- name: Generate app icons
|
||||
run: dart run flutter_launcher_icons
|
||||
|
||||
- name: Configure Rust application pods
|
||||
working-directory: ios
|
||||
run: pod install
|
||||
|
||||
- name: Build iOS (unsigned)
|
||||
run: |
|
||||
# Build Flutter iOS without codesigning
|
||||
flutter build ios --release --no-codesign --config-only \
|
||||
flutter build ios --release --no-codesign --config-only --target lib/main.dart \
|
||||
--dart-define="GIT_COMMIT=$(git rev-parse --short=8 HEAD)"
|
||||
|
||||
# Use xcodebuild with code signing disabled
|
||||
@@ -296,6 +289,12 @@ jobs:
|
||||
CODE_SIGN_IDENTITY="" \
|
||||
DEVELOPMENT_TEAM=""
|
||||
|
||||
- name: Audit Rust iOS archive before packaging
|
||||
run: |
|
||||
python3 scripts/check_backend_ios.py \
|
||||
ios/build/Runner.xcarchive/Products/Applications/Runner.app \
|
||||
--backend rust --archs arm64 --platform ios --release
|
||||
|
||||
- name: Create IPA
|
||||
env:
|
||||
VERSION: ${{ needs.get-version.outputs.version }}
|
||||
|
||||
Reference in New Issue
Block a user