name: Android CI on: push: branches: - main pull_request: branches: - main permissions: contents: read jobs: android: runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - name: Checkout uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 - name: Set up Java 17 uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin java-version: '17' - name: Verify Gradle supply chain shell: bash run: | set -euo pipefail test -x android/gradlew test -f android/gradlew.bat test -f android/gradle/wrapper/gradle-wrapper.jar test -s android/gradle/verification-metadata.xml test "$(sha256sum android/gradle/wrapper/gradle-wrapper.jar | awk '{print $1}')" = '7d3a4ac4de1c32b59bc6a4eb8ecb8e612ccd0cf1ae1e99f66902da64df296172' grep -qx 'distributionSha256Sum=efe9a3d147d948d7528a9887fa35abcf24ca1a43ad06439996490f77569b02d1' android/gradle/wrapper/gradle-wrapper.properties grep -q 'true' android/gradle/verification-metadata.xml ./android/gradlew --version - name: Set up Flutter uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2 with: flutter-version: '3.47.2' channel: stable cache: false - name: Create CI app config run: cp lib/logic/app_config.example.dart lib/logic/app_config.dart - name: Resolve dependencies run: flutter pub get - name: Verify dependency lock is committed run: git diff --exit-code -- pubspec.lock - name: Verify vendored runtime provenance shell: bash run: | set -euo pipefail PKG='local_packages/flutter_vless_android-1.1.5' test -f "$PKG/UPSTREAM" grep -q 'Tag: v1.1.5' "$PKG/UPSTREAM" grep -q 'path: local_packages/flutter_vless_android-1.1.5' pubspec.yaml ! grep -q 'patchFlutterVless' android/app/build.gradle.kts - name: Analyze run: flutter analyze - name: Test run: flutter test - name: Android lint working-directory: android run: ./gradlew :app:lintDebug --no-daemon - name: Verify production release config fails closed shell: bash working-directory: android run: | set -euo pipefail set +e output="$(./gradlew :app:verifyReleaseAppConfig --no-daemon 2>&1)" status=$? set -e printf '%s\n' "$output" test "$status" -ne 0 grep -Fq 'REVOLT_APP_CONFIG_SHA256 is required for production release builds' <<<"$output" - name: Cold APK build run: flutter build apk --debug - name: Verify vendored native source stayed immutable run: git diff --exit-code -- local_packages/flutter_vless_android-1.1.5 - name: Warm APK build run: flutter build apk --debug - name: Release R8 smoke build env: REVOLT_CI_RELEASE_SMOKE: 'true' run: | flutter build apk --release test -f build/app/outputs/flutter-apk/app-release.apk test -f build/app/outputs/mapping/release/mapping.txt - name: Verify tracked build inputs stayed immutable run: | git diff --exit-code -- \ pubspec.yaml \ pubspec.lock \ local_packages/flutter_vless_android-1.1.5 \ android/app/build.gradle.kts \ android/app/proguard-rules.pro \ android/gradle/verification-metadata.xml \ android/gradle/wrapper/gradle-wrapper.properties \ android/gradle/wrapper/gradle-wrapper.jar \ android/gradlew \ android/gradlew.bat - name: Upload APK uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: revoltvpn-debug-apk if-no-files-found: error path: build/app/outputs/flutter-apk/app-debug.apk - name: Upload resolved lockfile uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: revoltvpn-resolved-lockfile if-no-files-found: error path: pubspec.lock