name: Build Android APKs on: workflow_dispatch: inputs: tag: description: Release tag to draft required: true default: v0.3.0 permissions: contents: write jobs: build: name: Build ${{ matrix.abi }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - abi: arm64-v8a rust_target: aarch64-linux-android asset: Aethery-arm64-v8a.apk - abi: armeabi-v7a rust_target: armv7-linux-androideabi asset: Aethery-armeabi-v7a.apk steps: - name: Check out source uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: distribution: temurin java-version: "17" - name: Set up Android SDK uses: android-actions/setup-android@v3 - name: Install Android NDK and CMake run: | sdkmanager "ndk;26.3.11579264" "cmake;3.22.1" echo "ANDROID_NDK=$ANDROID_SDK_ROOT/ndk/26.3.11579264" >> "$GITHUB_ENV" echo "ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk/26.3.11579264" >> "$GITHUB_ENV" echo "ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/26.3.11579264" >> "$GITHUB_ENV" - name: Set up Rust uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.rust_target }} - name: Install cargo-ndk run: cargo install cargo-ndk --locked - name: Build Aether core working-directory: core/aether run: cargo ndk -t ${{ matrix.abi }} --platform 26 build --release --lib - name: Stage Aether library run: | mkdir -p app/src/main/jniLibs/${{ matrix.abi }} cp core/aether/target/${{ matrix.rust_target }}/release/libaether.so app/src/main/jniLibs/${{ matrix.abi }}/libaether.so - name: Bundle sing-box core env: SING_BOX_VERSION: 1.13.12 run: | case "${{ matrix.abi }}" in arm64-v8a) sing_box_arch=arm64 ;; armeabi-v7a) sing_box_arch=arm ;; esac mkdir -p "app/src/main/assets/cores/${{ matrix.abi }}" curl -fsSL "https://github.com/SagerNet/sing-box/releases/download/v${SING_BOX_VERSION}/sing-box-${SING_BOX_VERSION}-android-${sing_box_arch}.tar.gz" \ | tar -xz --strip-components=1 -C "app/src/main/assets/cores/${{ matrix.abi }}" - name: Decode release signing key env: KEYSTORE_BASE64: ${{ secrets.AETHERY_RELEASE_KEYSTORE_BASE64 }} run: | test -n "$KEYSTORE_BASE64" || { echo "Missing AETHERY_RELEASE_KEYSTORE_BASE64"; exit 1; } echo "$KEYSTORE_BASE64" | base64 --decode > "$RUNNER_TEMP/aethery-release.jks" - name: Build signed release APK env: AETHERY_KEYSTORE_PASSWORD: ${{ secrets.AETHERY_KEYSTORE_PASSWORD }} AETHERY_KEY_ALIAS: ${{ secrets.AETHERY_KEY_ALIAS }} AETHERY_KEY_PASSWORD: ${{ secrets.AETHERY_KEY_PASSWORD }} run: | test -n "$AETHERY_KEYSTORE_PASSWORD" && test -n "$AETHERY_KEY_ALIAS" && test -n "$AETHERY_KEY_PASSWORD" ./gradlew :app:assembleRelease -PtargetAbi=${{ matrix.abi }} -PaetheryKeystore="$RUNNER_TEMP/aethery-release.jks" - name: Name release APK run: | mkdir -p dist apk=$(find app/build/outputs/apk/release -name "*${{ matrix.abi }}*release.apk" -print -quit) test -n "$apk" cp "$apk" "dist/${{ matrix.asset }}" - name: Upload APK for release job uses: actions/upload-artifact@v4 with: name: ${{ matrix.asset }} path: dist/${{ matrix.asset }} if-no-files-found: error draft-release: name: Create draft release if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/') needs: build runs-on: ubuntu-latest steps: - name: Download APKs uses: actions/download-artifact@v4 with: path: dist merge-multiple: true - name: Upload direct APK assets to draft release uses: softprops/action-gh-release@v2 with: tag_name: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }} name: Aethery ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }} draft: false prerelease: false generate_release_notes: true files: | dist/Aethery-arm64-v8a.apk dist/Aethery-armeabi-v7a.apk