Update README with CI/CD and release signing instructions #5
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
| name: Build NeuralPulse APKs | |
| on: | |
| push: | |
| branches: [master, main] | |
| pull_request: | |
| branches: [master, main] | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v4 | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: '17' | |
| distribution: 'temurin' | |
| - name: Set up Android SDK | |
| uses: android-actions/setup-android@v3 | |
| - name: Accept Android SDK licenses | |
| run: yes | sdkmanager --licenses || true | |
| - name: Install required SDK platforms and build tools | |
| run: | | |
| sdkmanager "platforms;android-35" "build-tools;34.0.0" "platform-tools" | |
| - name: Cache Gradle packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| key: gradle-${{ hashFiles('**/*.gradle.kts', '**/gradle-wrapper.properties') }} | |
| restore-keys: gradle- | |
| - name: Grant execute permission for gradlew | |
| run: chmod +x gradlew | |
| - name: Decode Keystore | |
| env: | |
| ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | |
| if: env.ANDROID_KEYSTORE_BASE64 != '' | |
| run: | | |
| echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > app/release.jks | |
| echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > wear/release.jks | |
| # ── Phone companion app (works on any Android 10+ device) ── | |
| - name: Build phone app (debug) | |
| run: ./gradlew :app:assembleDebug --no-daemon --stacktrace | |
| - name: Build phone app (release) | |
| run: ./gradlew :app:assembleRelease --no-daemon | |
| env: | |
| ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} | |
| ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} | |
| ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} | |
| # ── Wear OS watch app (works on any Wear OS 3+ watch) ── | |
| - name: Build wear app (debug) | |
| run: ./gradlew :wear:assembleDebug --no-daemon --stacktrace | |
| - name: Build wear app (release) | |
| run: ./gradlew :wear:assembleRelease --no-daemon | |
| env: | |
| ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} | |
| ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} | |
| ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} | |
| - name: Standardize Release APK Names | |
| run: | | |
| # Copy phone release APK depending on whether it was signed | |
| if [ -f app/build/outputs/apk/release/app-release.apk ]; then | |
| cp app/build/outputs/apk/release/app-release.apk app/build/outputs/apk/release/app-release-final.apk | |
| else | |
| cp app/build/outputs/apk/release/app-release-unsigned.apk app/build/outputs/apk/release/app-release-final.apk | |
| fi | |
| # Copy wear release APK depending on whether it was signed | |
| if [ -f wear/build/outputs/apk/release/wear-release.apk ]; then | |
| cp wear/build/outputs/apk/release/wear-release.apk wear/build/outputs/apk/release/wear-release-final.apk | |
| else | |
| cp wear/build/outputs/apk/release/wear-release-unsigned.apk wear/build/outputs/apk/release/wear-release-final.apk | |
| fi | |
| - name: Clean Keystore | |
| if: always() | |
| run: | | |
| rm -f app/release.jks | |
| rm -f wear/release.jks | |
| # ── Upload all 4 APKs as build artifacts ── | |
| - name: Upload phone debug APK | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: NeuralPulse-phone-debug | |
| path: app/build/outputs/apk/debug/app-debug.apk | |
| retention-days: 30 | |
| - name: Upload phone release APK | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: NeuralPulse-phone-release | |
| path: app/build/outputs/apk/release/app-release-final.apk | |
| retention-days: 30 | |
| - name: Upload wear debug APK | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: NeuralPulse-wear-debug | |
| path: wear/build/outputs/apk/debug/wear-debug.apk | |
| retention-days: 30 | |
| - name: Upload wear release APK | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: NeuralPulse-wear-release | |
| path: wear/build/outputs/apk/release/wear-release-final.apk | |
| retention-days: 30 | |
| # ── Auto-tag release on push to master ── | |
| - name: Create GitHub Release | |
| if: github.ref == 'refs/heads/master' && github.event_name == 'push' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: build-${{ github.run_number }} | |
| name: "NeuralPulse Build #${{ github.run_number }}" | |
| body: | | |
| ## NeuralPulse Automatic Build | |
| ### Phone app (Android 10+ / API 29+) | |
| - `NeuralPulse-phone-debug.apk` — sideload directly, no signing needed | |
| - `NeuralPulse-phone-release-final.apk` — production build (signed if credentials supplied) | |
| ### Wear OS app (Wear OS 3+ / API 30+) | |
| - `NeuralPulse-wear-debug.apk` — sideload via ADB | |
| - `NeuralPulse-wear-release-final.apk` — production build (signed if credentials supplied) | |
| ### Device compatibility | |
| - **Phone**: Any Android 10+ device. Samsung Health SDK is optional; falls back to Health Connect on non-Samsung. | |
| - **Watch**: Any Wear OS 3+ watch. Samsung Health Sensor SDK is optional; falls back to Android Health Services on non-Galaxy watches. | |
| Commit: ${{ github.sha }} | |
| files: | | |
| app/build/outputs/apk/debug/app-debug.apk | |
| app/build/outputs/apk/release/app-release-final.apk | |
| wear/build/outputs/apk/debug/wear-debug.apk | |
| wear/build/outputs/apk/release/wear-release-final.apk | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |