Files
SpotiFLAC-Mobile/.github/workflows/ci.yml
T

271 lines
8.6 KiB
YAML

name: CI
on:
pull_request:
push:
branches:
- main
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
changes:
name: Detect changed paths
runs-on: ubuntu-latest
permissions:
pull-requests: read
outputs:
dart: ${{ steps.filter.outputs.dart }}
android: ${{ steps.filter.outputs.android }}
ios: ${{ steps.filter.outputs.ios }}
rust: ${{ steps.filter.outputs.rust }}
steps:
- name: Checkout repository
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- name: Filter paths
uses: dorny/paths-filter@0e4a8c6effa4802afeda77dc8d303f8176d7dfad # v3
id: filter
with:
filters: |
dart:
- 'third_party/audio_service/**'
- 'lib/**'
- 'test/**'
- 'android/app/src/test/resources/**'
- 'assets/**'
- 'pubspec.yaml'
- 'pubspec.lock'
- 'analysis_options.yaml'
- 'l10n.yaml'
- '.fvmrc'
- '.github/workflows/ci.yml'
rust:
- 'rust_backend/**'
- 'scripts/*rust*.sh'
- 'android/gradlew'
- 'android/gradle/wrapper/**'
- '.github/workflows/ci.yml'
ios:
- 'third_party/audio_service/**'
- 'ios/**'
- 'scripts/build_ios.sh'
- 'scripts/check_backend_ios.py'
- 'scripts/test_check_backend_ios.py'
- 'lib/**'
- 'assets/**'
- 'pubspec.yaml'
- 'pubspec.lock'
- 'l10n.yaml'
- '.fvmrc'
- '.github/workflows/ci.yml'
android:
- 'third_party/audio_service/**'
- 'android/**'
- 'rust_backend/**'
- 'scripts/build_android.sh'
- 'scripts/build_rust_backend.sh'
- 'scripts/check_backend_apk.py'
- 'scripts/test_check_backend_apk.py'
- 'lib/**'
- 'assets/**'
- 'pubspec.yaml'
- 'pubspec.lock'
- 'l10n.yaml'
- '.fvmrc'
- '.github/workflows/ci.yml'
flutter:
name: Flutter analyze & test
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.dart == 'true'
steps:
- name: Checkout repository
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- name: Setup Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
with:
channel: "stable"
flutter-version-file: .fvmrc
cache: true
- name: Cache pub dependencies
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: ~/.pub-cache
key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock') }}
restore-keys: pub-${{ runner.os }}-
- name: Get Flutter dependencies
run: flutter pub get
- 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
rust:
name: Rust checks & Android libraries
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.rust == 'true'
steps:
- name: Checkout repository
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- name: Setup Java for Android SDK tools
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: "temurin"
java-version: "25"
- name: Activate pinned Rust toolchain
working-directory: rust_backend
run: rustup show
- name: Install C binding generator dependencies
run: |
sudo apt-get update
sudo apt-get install -y libclang-dev
- 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: |
python3 -m unittest discover -s scripts -p 'test_check_backend_ios.py'
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 Rust builds & native tests
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.android == 'true'
steps:
- name: Checkout repository
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- name: Setup Java
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: "temurin"
java-version: "25"
- name: Setup Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
with:
channel: "stable"
flutter-version-file: .fvmrc
cache: true
- name: Setup Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
with:
gradle-version: "9.8.0"
# Cache public dependencies, not transforms of the decrypted SDK.
gradle-home-cache-includes: |
caches/modules-2
notifications
- name: Install Android SDK & NDK
run: |
yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses || true
"$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" \
"ndk;29.0.14206865" \
"platforms;android-37.0" \
"build-tools;37.0.0" \
"cmake;3.22.1"
echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/29.0.14206865" >> "$GITHUB_ENV"
- name: Test APK audits
run: |
python3 -m unittest discover -s scripts -p 'test_check_backend_apk.py'
- name: Get Flutter dependencies
run: flutter pub get
- name: Configure Flutter SDK for Gradle
run: echo "flutter.sdk=$FLUTTER_ROOT" > android/local.properties
- name: Install Rust application build and media test prerequisites
run: |
cd rust_backend
rustup show
sudo apt-get update
sudo apt-get install -y libclang-dev ffmpeg
ffmpeg -version
echo "SPOTIFLAC_TEST_FFMPEG=$(command -v ffmpeg)" >> "$GITHUB_ENV"
- 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
# PR builds use Gradle's test key; production signing stays in Release.
for abi in arm64-v8a armeabi-v7a; do
"$ANDROID_HOME/build-tools/37.0.0/apksigner" verify --verbose \
"build/app/outputs/flutter-apk/app-${abi}-release.apk"
done